1 /*
2  * Software License Agreement (BSD License)
3  *
4  *  Point Cloud Library (PCL) - www.pointclouds.org
5  *  Copyright (c) 2010-2012, Willow Garage, Inc.
6  *
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *
13  *   * Redistributions of source code must retain the above copyright
14  *     notice, this list of conditions and the following disclaimer.
15  *   * Redistributions in binary form must reproduce the above
16  *     copyright notice, this list of conditions and the following
17  *     disclaimer in the documentation and/or other materials provided
18  *     with the distribution.
19  *   * Neither the name of the copyright holder(s) nor the names of its
20  *     contributors may be used to endorse or promote products derived
21  *     from this software without specific prior written permission.
22  *
23  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  *  POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #pragma once
38 
39 /**
40  * \file pcl/pcl_macros.h
41  *
42  * \brief Defines all the PCL and non-PCL macros used
43  * \ingroup common
44  */
45 
46 #if defined __INTEL_COMPILER
47   #pragma warning disable 2196 2536 279
48 #endif
49 
50 #if defined _MSC_VER
51   // 4244 : conversion from 'type1' to 'type2', possible loss of data
52   // 4661 : no suitable definition provided for explicit template instantiation reques
53   // 4503 : decorated name length exceeded, name was truncated
54   // 4146 : unary minus operator applied to unsigned type, result still unsigned
55   #pragma warning (disable: 4018 4244 4267 4521 4251 4661 4305 4503 4146)
56 #endif
57 
58 #ifndef _USE_MATH_DEFINES
59   #define _USE_MATH_DEFINES
60 #endif
61 #include <cmath>
62 #include <cstdlib>
63 #include <iostream>
64 
65 // We need to check for GCC version, because GCC releases before 9 were implementing an
66 // OpenMP 3.1 data sharing rule, even OpenMP 4 is supported, so a plain OpenMP version 4 check
67 // isn't enough (see https://www.gnu.org/software/gcc/gcc-9/porting_to.html#ompdatasharing)
68 #if (defined _OPENMP && (_OPENMP <= 201307)) || (defined __GNUC__ && (__GNUC__ >= 6 && __GNUC__ < 9))
69   #define OPENMP_LEGACY_CONST_DATA_SHARING_RULE 1
70 #else
71   #define OPENMP_LEGACY_CONST_DATA_SHARING_RULE 0
72 #endif
73 
74 #include <pcl/pcl_config.h>
75 
76 #include <boost/preprocessor/arithmetic/add.hpp>
77 #include <boost/preprocessor/comparison/equal.hpp>
78 #include <boost/preprocessor/comparison/less.hpp>
79 #include <boost/preprocessor/control/if.hpp>
80 #include <boost/preprocessor/stringize.hpp>
81 
82 // MSVC < 2019 have issues:
83 // * can't short-circuiting logic in macros
84 // * don't define standard macros
85 // => this leads to annyoing C4067 warnings (see https://developercommunity.visualstudio.com/content/problem/327796/-has-cpp-attribute-emits-warning-is-wrong-highligh.html)
86 #if defined(_MSC_VER)
87   // nvcc on msvc can't work with [[deprecated]]
88   #if !defined(__CUDACC__)
89     #define _PCL_DEPRECATED_IMPL(Message) [[deprecated(Message)]]
90   #else
91     #define _PCL_DEPRECATED_IMPL(Message)
92   #endif
93 #elif __has_cpp_attribute(deprecated)
94   #define _PCL_DEPRECATED_IMPL(Message) [[deprecated(Message)]]
95 #else
96   #warning "You need to implement _PCL_DEPRECATED_IMPL for this compiler"
97   #define _PCL_DEPRECATED_IMPL(Message)
98 #endif
99 
100 // Macro for pragma operator
101 #if (defined (__GNUC__) || defined(__clang__))
102   #define PCL_PRAGMA(x) _Pragma (#x)
103 #elif _MSC_VER
104   #define PCL_PRAGMA(x) __pragma (#x)
105 #else
106   #define PCL_PRAGMA
107 #endif
108 
109 // Macro for emitting pragma warning for deprecated headers
110 #if (defined (__GNUC__) || defined(__clang__))
111   #define _PCL_DEPRECATED_HEADER_IMPL(Message) PCL_PRAGMA (GCC warning Message)
112 #elif _MSC_VER
113   #define _PCL_DEPRECATED_HEADER_IMPL(Message) PCL_PRAGMA (warning (Message))
114 #else
115   #warning "You need to implement _PCL_DEPRECATED_HEADER_IMPL for this compiler"
116   #define _PCL_DEPRECATED_HEADER_IMPL(Message)
117 #endif
118 
119 /**
120  * \brief A handy way to inform the user of the removal deadline
121  */
122 #define _PCL_PREPARE_REMOVAL_MESSAGE(Major, Minor, Msg)                                 \
123   Msg " (It will be removed in PCL " BOOST_PP_STRINGIZE(Major.Minor) ")"
124 
125 /**
126  * \brief Tests for Minor < PCL_MINOR_VERSION
127  * \details When PCL VERSION is of format `34.12.99`, this macro behaves as if it is
128  * already `34.13.0`, and allows for smoother transition for maintainers
129  */
130 #define _PCL_COMPAT_MINOR_VERSION(Minor, IfPass, IfFail)                                \
131   BOOST_PP_IF(BOOST_PP_EQUAL(PCL_REVISION_VERSION, 99),                                 \
132     BOOST_PP_IF(BOOST_PP_LESS(BOOST_PP_ADD(PCL_MINOR_VERSION, 1), Minor), IfPass, IfFail),           \
133     BOOST_PP_IF(BOOST_PP_LESS(PCL_MINOR_VERSION, Minor), IfPass, IfFail))
134 
135 /**
136  * \brief Tests for Major == PCL_MAJOR_VERSION
137  * \details When PCL VERSION is of format `34.99.12`, this macro behaves as if it is
138  * already `35.0.0`, and allows for smoother transition for maintainers
139  */
140 #define _PCL_COMPAT_MAJOR_VERSION(Major, IfPass, IfFail)                                \
141   BOOST_PP_IF(BOOST_PP_EQUAL(PCL_MINOR_VERSION, 99),                                    \
142     BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_ADD(PCL_MAJOR_VERSION, 1), Major), IfPass, IfFail),          \
143     BOOST_PP_IF(BOOST_PP_EQUAL(PCL_MAJOR_VERSION, Major), IfPass, IfFail))
144 
145 /**
146  * \brief macro for compatibility across compilers and help remove old deprecated
147  *        items for the Major.Minor release
148  *
149  * \details compiler errors of `unneeded_deprecation` and `major_version_mismatch`
150  * are hints to the developer that those items can be safely removed.
151  * Behavior of PCL_DEPRECATED(1, 99, "Not needed anymore")
152  *   * till PCL 1.98: "Not needed anymore (It will be removed in PCL 1.99)"
153  *   * PCL 1.99 onwards: compiler error with "unneeded_deprecation"
154  *   * PCL 2.0 onwards: compiler error with "major_version_mismatch"
155  */
156 #define PCL_DEPRECATED(Major, Minor, Message)                                          \
157   _PCL_COMPAT_MAJOR_VERSION(                                                           \
158       Major,                                                                           \
159       _PCL_COMPAT_MINOR_VERSION(                                                       \
160           Minor,                                                                       \
161           _PCL_DEPRECATED_IMPL(_PCL_PREPARE_REMOVAL_MESSAGE(Major, Minor, Message)),   \
162           unneeded_deprecation),                                                       \
163       major_version_mismatch)
164 
165 /**
166  * \brief macro for compatibility across compilers and help remove old deprecated
167  *        headers for the Major.Minor release
168  *
169  * \details compiler errors of `unneeded_header` and `major_version_mismatch`
170  * are hints to the developer that those items can be safely removed.
171  * Behavior of PCL_DEPRECATED_HEADER(1, 99, "Use file <newfile.h> instead.")
172  *   * till PCL 1.98: "This header is deprecated. Use file <newfile.h> instead. (It will be removed in PCL 1.99)"
173  *   * PCL 1.99 onwards: compiler error with "unneeded_header"
174  *   * PCL 2.0 onwards: compiler error with "major_version_mismatch"
175  */
176 #define PCL_DEPRECATED_HEADER(Major, Minor, Message)                                   \
177   _PCL_COMPAT_MAJOR_VERSION(                                                           \
178       Major,                                                                           \
179       _PCL_COMPAT_MINOR_VERSION(                                                       \
180           Minor,                                                                       \
181           _PCL_DEPRECATED_HEADER_IMPL(_PCL_PREPARE_REMOVAL_MESSAGE(                    \
182               Major,                                                                   \
183               Minor,                                                                   \
184               "This header is deprecated. " Message)),                                 \
185           unneeded_header),                                                            \
186       major_version_mismatch)
187 
188 #if defined _WIN32
189 // Define math constants, without including math.h, to prevent polluting global namespace with old math methods
190 // Copied from math.h
191 // Check for M_2_SQRTPI since the cmath header on mingw-w64 doesn't seem to define
192 // _MATH_DEFINES_DEFINED when included with _USE_MATH_DEFINES
193 #if !defined _MATH_DEFINES_DEFINED && !defined M_2_SQRTPI
194   #define _MATH_DEFINES_DEFINED
195 
196   #define M_E        2.71828182845904523536   // e
197   #define M_LOG2E    1.44269504088896340736   // log2(e)
198   #define M_LOG10E   0.434294481903251827651  // log10(e)
199   #define M_LN2      0.693147180559945309417  // ln(2)
200   #define M_LN10     2.30258509299404568402   // ln(10)
201   #define M_PI       3.14159265358979323846   // pi
202   #define M_PI_2     1.57079632679489661923   // pi/2
203   #define M_PI_4     0.785398163397448309616  // pi/4
204   #define M_1_PI     0.318309886183790671538  // 1/pi
205   #define M_2_PI     0.636619772367581343076  // 2/pi
206   #define M_2_SQRTPI 1.12837916709551257390   // 2/sqrt(pi)
207   #define M_SQRT2    1.41421356237309504880   // sqrt(2)
208   #define M_SQRT1_2  0.707106781186547524401  // 1/sqrt(2)
209 #endif
210 
211 #if defined _MSC_VER
212   // Stupid. This should be removed when all the PCL dependencies have min/max fixed.
213   #ifndef NOMINMAX
214     #define NOMINMAX
215   #endif
216 
217   #define __PRETTY_FUNCTION__ __FUNCTION__
218   #define __func__ __FUNCTION__
219 #endif
220 #endif // defined _WIN32
221 
222 #ifndef DEG2RAD
223 #define DEG2RAD(x) ((x)*0.017453293)
224 #endif
225 
226 #ifndef RAD2DEG
227 #define RAD2DEG(x) ((x)*57.29578)
228 #endif
229 
230 /** \brief Macro that maps version information given by major.minor.patch to a linear integer value to enable easy comparison
231  */
232 #define PCL_LINEAR_VERSION(major,minor,patch) ((major)<<16|(minor)<<8|(patch))
233 
234 /** Win32 doesn't seem to have rounding functions.
235   * Therefore implement our own versions of these functions here.
236   */
237 
238 __inline double
pcl_round(double number)239 pcl_round (double number)
240 {
241   return (number < 0.0 ? std::ceil (number - 0.5) : std::floor (number + 0.5));
242 }
243 __inline float
pcl_round(float number)244 pcl_round (float number)
245 {
246   return (number < 0.0f ? std::ceil (number - 0.5f) : std::floor (number + 0.5f));
247 }
248 
249 #ifdef __GNUC__
250 #define pcl_lrint(x) (lrint(static_cast<double> (x)))
251 #define pcl_lrintf(x) (lrintf(static_cast<float> (x)))
252 #else
253 #define pcl_lrint(x) (static_cast<long int>(pcl_round(x)))
254 #define pcl_lrintf(x) (static_cast<long int>(pcl_round(x)))
255 #endif
256 
257 #ifdef WIN32
258 #define pcl_sleep(x) Sleep(1000*(x))
259 #else
260 #define pcl_sleep(x) sleep(x)
261 #endif
262 
263 #ifndef PVAR
264   #define PVAR(s) \
265     #s << " = " << (s) << std::flush
266 #endif
267 #ifndef PVARN
268 #define PVARN(s) \
269   #s << " = " << (s) << "\n"
270 #endif
271 #ifndef PVARC
272 #define PVARC(s) \
273   #s << " = " << (s) << ", " << std::flush
274 #endif
275 #ifndef PVARS
276 #define PVARS(s) \
277   #s << " = " << (s) << " " << std::flush
278 #endif
279 #ifndef PVARA
280 #define PVARA(s) \
281   #s << " = " << RAD2DEG(s) << "deg" << std::flush
282 #endif
283 #ifndef PVARAN
284 #define PVARAN(s) \
285   #s << " = " << RAD2DEG(s) << "deg\n"
286 #endif
287 #ifndef PVARAC
288 #define PVARAC(s) \
289   #s << " = " << RAD2DEG(s) << "deg, " << std::flush
290 #endif
291 #ifndef PVARAS
292 #define PVARAS(s) \
293   #s << " = " << RAD2DEG(s) << "deg " << std::flush
294 #endif
295 
296 #define FIXED(s) \
297   std::fixed << s << std::resetiosflags(std::ios_base::fixed)
298 
299 #ifndef ERASE_STRUCT
300 #define ERASE_STRUCT(var) memset(&var, 0, sizeof(var))
301 #endif
302 
303 #ifndef ERASE_ARRAY
304 #define ERASE_ARRAY(var, size) memset(var, 0, size*sizeof(*var))
305 #endif
306 
307 #ifndef SET_ARRAY
308 #define SET_ARRAY(var, value, size) { for (decltype(size) i = 0; i < size; ++i) var[i]=value; }
309 #endif
310 
311 #ifndef PCL_EXTERN_C
312     #ifdef __cplusplus
313         #define PCL_EXTERN_C extern "C"
314     #else
315         #define PCL_EXTERN_C
316     #endif
317 #endif
318 
319 #if defined WIN32 || defined _WIN32 || defined WINCE || defined __MINGW32__
320     #ifdef PCLAPI_EXPORTS
321         #define PCL_EXPORTS __declspec(dllexport)
322     #else
323         #define PCL_EXPORTS
324     #endif
325 #else
326     #define PCL_EXPORTS
327 #endif
328 
329 #if defined WIN32 || defined _WIN32
330     #define PCL_CDECL __cdecl
331     #define PCL_STDCALL __stdcall
332 #else
333     #define PCL_CDECL
334     #define PCL_STDCALL
335 #endif
336 
337 #ifndef PCLAPI
338     #define PCLAPI(rettype) PCL_EXTERN_C PCL_EXPORTS rettype PCL_CDECL
339 #endif
340 
341 //for clang cf. http://clang.llvm.org/docs/LanguageExtensions.html
342 #ifndef __has_extension
343   #define __has_extension(x) 0 // Compatibility with pre-3.0 compilers.
344 #endif
345 
346 #if defined (__GNUC__) || defined (__PGI) || defined (__IBMCPP__) || defined (__SUNPRO_CC)
347   #define PCL_ALIGN(alignment) __attribute__((aligned(alignment)))
348 #elif defined (_MSC_VER)
349   #define PCL_ALIGN(alignment) __declspec(align(alignment))
350 #else
351   #error Alignment not supported on your platform
352 #endif
353 
354 #if defined(__GLIBC__) && PCL_LINEAR_VERSION(__GLIBC__,__GLIBC_MINOR__,0)>PCL_LINEAR_VERSION(2,8,0)
355   #define GLIBC_MALLOC_ALIGNED 1
356 #else
357   #define GLIBC_MALLOC_ALIGNED 0
358 #endif
359 
360 #if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
361   #define FREEBSD_MALLOC_ALIGNED 1
362 #else
363   #define FREEBSD_MALLOC_ALIGNED 0
364 #endif
365 
366 #if defined(__APPLE__) || defined(_WIN64) || GLIBC_MALLOC_ALIGNED || FREEBSD_MALLOC_ALIGNED
367   #define MALLOC_ALIGNED 1
368 #endif
369 
370 #if defined (HAVE_MM_MALLOC)
371   // Intel compiler defines an incompatible _mm_malloc signature
372   #if defined(__INTEL_COMPILER)
373     #include <malloc.h>
374   #else
375     #include <mm_malloc.h>
376   #endif
377 #endif
378 
379 namespace pcl {
380 
381 #ifdef __DragonFly__
382 #define HAVE_POSIX_MEMALIGN
383 #endif
384 
385 inline void*
aligned_malloc(std::size_t size)386 aligned_malloc(std::size_t size)
387 {
388   void* ptr;
389 #if defined(MALLOC_ALIGNED)
390   ptr = std::malloc(size);
391 #elif defined(HAVE_POSIX_MEMALIGN)
392   if (posix_memalign(&ptr, 16, size))
393     ptr = 0;
394 #elif defined(HAVE_MM_MALLOC)
395   ptr = _mm_malloc(size, 16);
396 #elif defined(_MSC_VER)
397   ptr = _aligned_malloc(size, 16);
398 #elif defined(ANDROID)
399   ptr = memalign(16, size);
400 #else
401 #error aligned_malloc not supported on your platform
402   ptr = 0;
403 #endif
404   return (ptr);
405 }
406 
407 inline void
aligned_free(void * ptr)408 aligned_free(void* ptr)
409 {
410 #if defined(MALLOC_ALIGNED) || defined(HAVE_POSIX_MEMALIGN)
411   std::free(ptr);
412 #elif defined(HAVE_MM_MALLOC)
413   _mm_free(ptr);
414 #elif defined(_MSC_VER)
415   _aligned_free(ptr);
416 #elif defined(ANDROID)
417   free(ptr);
418 #else
419 #error aligned_free not supported on your platform
420 #endif
421 }
422 
423 } // namespace pcl
424 
425 /**
426  * \brief Macro to add a no-op or a fallthrough attribute based on compiler feature
427  *
428  * \ingroup common
429  */
430 #if (__cplusplus >= 201703L) || (defined(_MSC_VER) && (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703L))
431   #define PCL_FALLTHROUGH [[fallthrough]];
432 #elif defined(__clang__)
433   #define PCL_FALLTHROUGH [[clang::fallthrough]];
434 #elif defined(__GNUC__) && (__GNUC__ >= 7)
435   #define PCL_FALLTHROUGH [[gnu::fallthrough]];
436 #else
437   #define PCL_FALLTHROUGH
438 #endif
439 
440 #if (__cplusplus >= 201703L) || (defined(_MSC_VER) && (_MSC_VER >= 1911) && (_MSVC_LANG >= 201703L))
441   #define PCL_NODISCARD [[nodiscard]]
442 #elif defined(__clang__) && (PCL_LINEAR_VERSION(__clang_major__, __clang_minor__, 0) >= PCL_LINEAR_VERSION(3, 9, 0))
443   #define PCL_NODISCARD [[clang::warn_unused_result]]
444 #elif defined(__GNUC__)
445   #define PCL_NODISCARD [[gnu::warn_unused_result]]
446 #else
447   #define PCL_NODISCARD
448 #endif
449 
450 #ifdef __cpp_if_constexpr
451   #define PCL_IF_CONSTEXPR(x) if constexpr(x)
452 #else
453   #define PCL_IF_CONSTEXPR(x) if (x)
454 #endif
455