1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef PATH_MATH_COMPILER_H 18 #define PATH_MATH_COMPILER_H 19 20 #include <type_traits> 21 22 #if defined (WIN32) 23 24 #ifdef max 25 #undef max 26 #endif 27 28 #ifdef min 29 #undef min 30 #endif 31 32 #ifdef far 33 #undef far 34 #endif 35 36 #ifdef near 37 #undef near 38 #endif 39 40 #endif 41 42 // compatibility with non-clang compilers... 43 #ifndef __has_attribute 44 #define __has_attribute(x) 0 45 #endif 46 #ifndef __has_builtin 47 #define __has_builtin(x) 0 48 #endif 49 50 #if __has_builtin(__builtin_expect) 51 # ifdef __cplusplus 52 # define MATH_LIKELY( exp ) (__builtin_expect( !!(exp), true )) 53 # define MATH_UNLIKELY( exp ) (__builtin_expect( !!(exp), false )) 54 # else 55 # define MATH_LIKELY( exp ) (__builtin_expect( !!(exp), 1 )) 56 # define MATH_UNLIKELY( exp ) (__builtin_expect( !!(exp), 0 )) 57 # endif 58 #else 59 # define MATH_LIKELY( exp ) (exp) 60 # define MATH_UNLIKELY( exp ) (exp) 61 #endif 62 63 #if __has_attribute(unused) 64 # define MATH_UNUSED __attribute__((unused)) 65 #else 66 # define MATH_UNUSED 67 #endif 68 69 #if __has_attribute(pure) 70 # define MATH_PURE __attribute__((pure)) 71 #else 72 # define MATH_PURE 73 #endif 74 75 #ifdef _MSC_VER 76 # define MATH_EMPTY_BASES __declspec(empty_bases) 77 78 // MSVC does not support loop unrolling hints 79 # define MATH_NOUNROLL 80 81 // Sadly, MSVC does not support __builtin_constant_p 82 # ifndef MAKE_CONSTEXPR 83 # define MAKE_CONSTEXPR(e) (e) 84 # endif 85 86 // About value initialization, the C++ standard says: 87 // if T is a class type with a default constructor that is neither user-provided nor deleted 88 // (that is, it may be a class with an implicitly-defined or defaulted default constructor), 89 // the object is zero-initialized and then it is default-initialized 90 // if it has a non-trivial default constructor; 91 // Unfortunately, MSVC always calls the default constructor, even if it is trivial, which 92 // breaks constexpr-ness. To workaround this, we're always zero-initializing TVecN<> 93 # define MATH_CONSTEXPR_INIT {} 94 # define MATH_DEFAULT_CTOR {} 95 # define MATH_DEFAULT_CTOR_CONSTEXPR constexpr 96 # define CONSTEXPR_IF_NOT_MSVC // when declared constexpr, msvc fails with 97 // "failure was caused by cast of object of dynamic type" 98 99 #else // _MSC_VER 100 101 # define MATH_EMPTY_BASES 102 // C++11 allows pragmas to be specified as part of defines using the _Pragma syntax. 103 # define MATH_NOUNROLL _Pragma("nounroll") 104 105 # ifndef MAKE_CONSTEXPR 106 # define MAKE_CONSTEXPR(e) __builtin_constant_p(e) ? (e) : (e) 107 # endif 108 109 # define MATH_CONSTEXPR_INIT 110 # define MATH_DEFAULT_CTOR = default; 111 # define MATH_DEFAULT_CTOR_CONSTEXPR 112 # define CONSTEXPR_IF_NOT_MSVC constexpr 113 114 #endif // _MSC_VER 115 116 namespace filament::math { 117 118 // MSVC 2019 16.4 doesn't seem to like it when we specialize std::is_arithmetic for 119 // filament::math::half, so we're forced to create our own is_arithmetic here and specialize it 120 // inside of half.h. 121 template<typename T> 122 struct is_arithmetic : std::integral_constant<bool, 123 std::is_integral<T>::value || std::is_floating_point<T>::value> { 124 }; 125 126 } // filament::math 127 128 #endif // PATH_MATH_COMPILER_H 129