1 /*
2  *  Copyright (c) 2004-2010, Bruno Levy
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *
8  *  * Redistributions of source code must retain the above copyright notice,
9  *  this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright notice,
11  *  this list of conditions and the following disclaimer in the documentation
12  *  and/or other materials provided with the distribution.
13  *  * Neither the name of the ALICE Project-Team nor the names of its
14  *  contributors may be used to endorse or promote products derived from this
15  *  software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  *  POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  If you modify this software, you should include a notice giving the
30  *  name of the person performing the modification, the date of modification,
31  *  and the reason for such modification.
32  *
33  *  Contact: Bruno Levy
34  *
35  *     levy@loria.fr
36  *
37  *     ALICE Project
38  *     LORIA, INRIA Lorraine,
39  *     Campus Scientifique, BP 239
40  *     54506 VANDOEUVRE LES NANCY CEDEX
41  *     FRANCE
42  *
43  */
44 
45 #ifndef OPENNL_PRIVATE_H
46 #define OPENNL_PRIVATE_H
47 
48 #include "nl.h"
49 #include <stdlib.h>
50 #include <string.h>
51 #include <stdio.h>
52 #include <math.h>
53 
54 #ifndef NDEBUG
55 #define NL_DEBUG
56 #endif
57 
58 /**
59  * \file geogram/NL/nl_private.h
60  * \brief Some macros and functions used internally by OpenNL.
61  */
62 
63 #if defined(__APPLE__) && defined(__MACH__)
64 /**
65  * \brief Defined if compiled on a Mac OS/X platform.
66  */
67 #define NL_OS_APPLE
68 #endif
69 
70 #if defined(__linux__) || defined(__DragonFly__) || defined(__ANDROID__) || defined(NL_OS_APPLE)
71 /**
72  * \brief Defined if compiled on a Unix-like platform.
73  */
74 #define NL_OS_UNIX
75 #endif
76 
77 
78 #if defined(WIN32) || defined(_WIN64)
79 /**
80  * \brief Defined if compiled on a Windows platform.
81  */
82 #define NL_OS_WINDOWS
83 #endif
84 
85 /**
86  * \brief Suppresses unsused argument warnings
87  * \details Some callbacks do not necessary use all their
88  *  arguments.
89  * \param[in] x the argument to be tagged as used
90  */
91 #define nl_arg_used(x) (void)x
92 
93 /**
94  * \name Assertion checks
95  * @{
96  */
97 
98 #if defined(__clang__) || defined(__GNUC__)
99 #define NL_NORETURN __attribute__((noreturn))
100 #else
101 #define NL_NORETURN
102 #endif
103 
104 #if defined(_MSC_VER)
105 #define NL_NORETURN_DECL __declspec(noreturn)
106 #else
107 #define NL_NORETURN_DECL
108 #endif
109 
110 /**
111  * \brief Displays an error message and aborts the program when
112  *  an assertion failed.
113  * \details Called by nl_assert() whenever the assertion failed
114  * \param[in] cond the textual representation of the condition
115  * \param[in] file the source filename
116  * \param[in] line the line number
117  */
118 NL_NORETURN_DECL void nl_assertion_failed(
119     const char* cond, const char* file, int line
120 ) NL_NORETURN;
121 
122 /**
123  * \brief Displays an error message and aborts the program
124  *  when a range assertion failed.
125  * \details Called by nl_range_assert() whenever the assertion failed
126  * \param[in] x the variable
127  * \param[in] min_val the minimum value
128  * \param[in] max_val the maximum value
129  * \param[in] file the source filename
130  * \param[in] line the line number
131  */
132 NL_NORETURN_DECL void nl_range_assertion_failed(
133     double x, double min_val, double max_val, const char* file, int line
134 ) NL_NORETURN;
135 
136 /**
137  * \brief Displays an error message and aborts the program
138  *  when the execution flow reached a point it should not
139  *  have reached.
140  * \details called by nl_assert_not_reached
141  * \param[in] file the source filename
142  * \param[in] line the line number
143  */
144 NL_NORETURN_DECL void nl_should_not_have_reached(
145     const char* file, int line
146 ) NL_NORETURN;
147 
148 /**
149  * \brief Tests an assertion and aborts the program if the test fails
150  * \param[in] x the condition to be tested
151  */
152 #define nl_assert(x) {                                          \
153     if(!(x)) {                                                  \
154         nl_assertion_failed(#x,__FILE__, __LINE__) ;            \
155     }                                                           \
156 }
157 
158 /**
159  * \brief Tests a range assertion and aborts the program if the test fails
160  * \param[in] x the variable to be tested
161  * \param[in] min_val the minimum admissible value for the variable
162  * \param[in] max_val the maximum admissible value for the variable
163  */
164 #define nl_range_assert(x,min_val,max_val) {                         \
165     if(((int)(x) < (int)(min_val)) || ((int)(x) > (int)(max_val))) { \
166         nl_range_assertion_failed(x, min_val, max_val,               \
167             __FILE__, __LINE__                                       \
168         ) ;                                                          \
169     }                                                                \
170 }
171 
172 /**
173  * \brief Triggers an assertion failure when the execution flow
174  *  reaches a specific location in the code.
175  */
176 #define nl_assert_not_reached {                                 \
177     nl_should_not_have_reached(__FILE__, __LINE__) ;            \
178 }
179 
180 #ifdef NL_DEBUG
181     #define nl_debug_assert(x) nl_assert(x)
182     #define nl_debug_range_assert(x,min_val,max_val)            \
183                                nl_range_assert(x,min_val,max_val)
184 #else
185     #define nl_debug_assert(x)
186     #define nl_debug_range_assert(x,min_val,max_val)
187 #endif
188 
189 #ifdef NL_PARANOID
190     #define nl_parano_assert(x) nl_assert(x)
191     #define nl_parano_range_assert(x,min_val,max_val)           \
192                                nl_range_assert(x,min_val,max_val)
193 #else
194     #define nl_parano_assert(x)
195     #define nl_parano_range_assert(x,min_val,max_val)
196 #endif
197 
198 /**
199  * @}
200  * \name Error reporting
201  * @{
202  */
203 
204 /**
205  * \brief Displays an error message
206  * \param[in] function name of the function that triggered the error
207  * \param[in] message error message
208  */
209 void nlError(const char* function, const char* message) ;
210 
211 /**
212  * \brief Displays a warning message
213  * \param[in] function name of the function that triggered the error
214  * \param[in] message warning message
215  */
216 void nlWarning(const char* function, const char* message) ;
217 
218 /**
219  * @}
220  * \name OS
221  * @{
222  */
223 
224 /**
225  * \brief Gets the current time in seconds
226  * \return the current time in seconds (starting from a given reference time)
227  */
228 NLdouble nlCurrentTime(void);
229 
230 
231 /**
232  * \brief Gets the number of cores
233  * \return the number of cores obtained from OpenMP if supported, or 1
234  */
235 NLuint nlGetNumCores(void);
236 
237 /**
238  * \brief Gets the number of threads
239  * \return the number of threads used by OpenMP if supported, or 1
240  */
241 NLuint nlGetNumThreads(void);
242 
243 /**
244  * \brief Sets the number of threads
245  * \param[in] nb_threads number of threads to be used by OpenMP,
246  *   ignored if OpenMP is not supported.
247  */
248 void nlSetNumThreads(NLuint nb_threads);
249 
250 /**
251  * \brief Type for manipulating DLL/shared object/dylib handles.
252  */
253 typedef void* NLdll;
254 
255 
256 /**
257  * \brief Flag for nlOpenDLL(), resolve all symbols when opening the DLL.
258  * \see nlOpenDLL()
259  */
260 #define NL_LINK_NOW    1
261 
262 /**
263  * \brief Flag for nlOpenDLL(), resolve symbols only when they are called.
264  * \see nlOpenDLL()
265  */
266 #define NL_LINK_LAZY   2
267 
268 /**
269  * \brief Flag for nlOpenDLL(), add all loaded symbols to global namespace.
270  */
271 #define NL_LINK_GLOBAL 4
272 
273 /**
274  * \brief Flag for nlOpenDLL(), do not display messages.
275  */
276 #define NL_LINK_QUIET  8
277 
278 /**
279  * \brief Flag for nlOpenDLL(), use fallback geogram numerical library if
280  *  library is not found in the system.
281  */
282 #define NL_LINK_USE_FALLBACK 16
283 
284 /**
285  * \brief Dynamically links a DLL/shared object/dylib to the current process.
286  * \param[in] filename the file name fo the DLL/shared object/dylib.
287  * \param[in] flags an or-combination of NL_LINK_NOW, NL_LINK_LAZY, NL_LINK_GLOBAL,
288  *  NL_LINK_QUIET.
289  * \return a handle to the DLL/shared object/dylib or NULL if it could not
290  *  be found.
291  */
292 NLdll nlOpenDLL(const char* filename, NLenum flags);
293 
294 /**
295  * \brief Closes a DLL/shared object/dylib.
296  * \param[in] handle a handle to a DLL/shared object/dylib that was previously
297  *  obtained by nlOpenDLL()
298  */
299 void nlCloseDLL(NLdll handle);
300 
301 /**
302  * \brief Finds a function in a DLL/shared object/dylib.
303  * \param[in] handle a handle to a DLL/shared object/dylib that was previously
304  *  obtained by nlOpenDLL()
305  * \param[in] funcname the name of the function
306  * \return a pointer to the function or NULL if no such function was found
307  */
308 NLfunc nlFindFunction(NLdll handle, const char* funcname);
309 
310 /******************************************************************************/
311 /* classic macros */
312 
313 #ifndef MIN
314 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
315 #endif
316 
317 #ifndef MAX
318 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
319 #endif
320 
321 
322 /**
323  * @}
324  * \name Memory management
325  * @{
326  */
327 
328 /**
329  * \brief Allocates a new element
330  * \details Memory is zeroed after allocation
331  * \param[in] T type of the element to be allocated
332  */
333 #define NL_NEW(T)                (T*)(calloc(1, sizeof(T)))
334 
335 /**
336  * \brief Allocates a new array of elements
337  * \details Memory is zeroed after allocation
338  * \param[in] T type of the elements
339  * \param[in] NB number of elements
340  */
341 #define NL_NEW_ARRAY(T,NB)       (T*)(calloc((size_t)(NB),sizeof(T)))
342 
343 /**
344  * \brief Changes the size of an already allocated array of elements
345  * \details Memory is zeroed after allocation
346  * \param[in] T type of the elements
347  * \param[in,out] x a pointer to the array to be resized
348  * \param[in] NB number of elements
349  */
350 #define NL_RENEW_ARRAY(T,x,NB)   (T*)(realloc(x,(size_t)(NB)*sizeof(T)))
351 
352 /**
353  * \brief Deallocates an element
354  * \param[in,out] x a pointer to the element to be deallocated
355  */
356 #define NL_DELETE(x)             free(x); x = NULL
357 
358 /**
359  * \brief Deallocates an array
360  * \param[in,out] x a pointer to the first element of the array to
361  *  be deallocated
362  */
363 #define NL_DELETE_ARRAY(x)       free(x); x = NULL
364 
365 /**
366  * \brief Clears an element
367  * \param[in] T type of the element to be cleared
368  * \param[in,out] x a pointer to the element
369  */
370 #define NL_CLEAR(T, x)           memset(x, 0, sizeof(T))
371 
372 /**
373  * \brief Clears an array of elements
374  * \param[in] T type of the element to be cleared
375  * \param[in,out] x a pointer to the element
376  * \param[in] NB number of elements
377  */
378 #define NL_CLEAR_ARRAY(T,x,NB)   memset(x, 0, (size_t)(NB)*sizeof(T))
379 
380 /**
381  * @}
382  * \name Integer bounds
383  * @{
384  */
385 
386 /**
387  * \brief Maximum unsigned 32 bits integer
388  */
389 #define NL_UINT_MAX 0xffffffff
390 
391 /**
392  * \brief Maximum unsigned 16 bits integer
393  */
394 #define NL_USHORT_MAX 0xffff
395 
396 /**
397  * @}
398  * \name Logging and messages
399  * @{
400  */
401 
402 extern NLprintfFunc nl_printf;
403 
404 extern NLfprintfFunc nl_fprintf;
405 
406 /**
407  * @}
408  */
409 
410 #endif
411