JPL Spatial
Sound spatialization and propagation library
Loading...
Searching...
No Matches
Core.h
Go to the documentation of this file.
1//
2// ██╗██████╗ ██╗ ██╗██████╗ ███████╗
3// ██║██╔══██╗ ██║ ██║██╔══██╗██╔════╝ ** JPLSpatial **
4// ██║██████╔╝ ██║ ██║██████╔╝███████╗
5// ██ ██║██╔═══╝ ██║ ██║██╔══██╗╚════██║ https://github.com/Jaytheway/JPLSpatial
6// ╚█████╔╝██║ ███████╗██║██████╔╝███████║
7// ╚════╝ ╚═╝ ╚══════╝╚═╝╚═════╝ ╚══════╝
8//
9// Copyright 2024 Jaroslav Pevno, JPLSpatial is offered under the terms of the ISC license:
10//
11// Permission to use, copy, modify, and/or distribute this software for any purpose with or
12// without fee is hereby granted, provided that the above copyright notice and this permission
13// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
14// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
16// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#pragma once
21
22// Thanks Jorrit Rouwe and his JoltPhysics library for most of the boilerplate below
23// https://github.com/jrouwe/JoltPhysics
24
25#ifndef JPL_CORE_DEFINED
26#define JPL_CORE_DEFINED
27
28//==============================================================================
29// Determine platform
30#if defined(JPL_PLATFORM_BLUE)
31 // Correct define already defined, this overrides everything else
32#elif defined(_WIN32) || defined(_WIN64)
33 #include <winapifamily.h>
34 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
35 #define JPL_PLATFORM_WINDOWS_UWP // Building for Universal Windows Platform
36 #endif
37 #define JPL_PLATFORM_WINDOWS
38#elif defined(__ANDROID__) // Android is linux too, so that's why we check it first
39 #define JPL_PLATFORM_ANDROID
40#elif defined(__linux__)
41 #define JPL_PLATFORM_LINUX
42#elif defined(__FreeBSD__)
43 #define JPL_PLATFORM_FREEBSD
44#elif defined(__APPLE__)
45 #include <TargetConditionals.h>
46 #if defined(TARGET_OS_IPHONE) && !TARGET_OS_IPHONE
47 #define JPL_PLATFORM_MACOS
48 #else
49 #define JPL_PLATFORM_IOS
50 #endif
51#elif defined(__EMSCRIPTEN__)
52 #define JPL_PLATFORM_WASM
53#endif
54
55//==============================================================================
56// Determine compiler
57#if defined(__clang__)
58 #define JPL_COMPILER_CLANG
59#elif defined(__GNUC__)
60 #define JPL_COMPILER_GCC
61#elif defined(_MSC_VER)
62 #define JPL_COMPILER_MSVC
63#endif
64
65//==============================================================================
66// Detect CPU architecture
67#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
68 //==========================================================================
69 // X86 CPU architecture
70 #define JPL_CPU_X86
71
72 #if defined(__x86_64__) || defined(_M_X64)
73 #define JPL_CPU_ADDRESS_BITS 64
74 #else
75 #error ""32-bit architecture is not supported""
76 #define JPL_CPU_ADDRESS_BITS 32
77 #endif
78 #define JPL_USE_SSE
79 #define JPL_VECTOR_ALIGNMENT 16
80 #define JPL_DVECTOR_ALIGNMENT 32
81
82 //==========================================================================
83 // Detect enabled instruction sets
84
85 // Detect compiler-enabled features when no authoritative configuration
86 // was supplied by the build system.
87 #if !defined(JPL_SIMD_CONFIGURED)
88 #if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && !defined(JPL_USE_AVX512)
89 #define JPL_USE_AVX512
90 #endif
91
92 #if defined(__AVX2__) && !defined(JPL_USE_AVX2)
93 #define JPL_USE_AVX2
94 #endif
95
96 #if defined(__AVX__) && !defined(JPL_USE_AVX)
97 #define JPL_USE_AVX
98 #endif
99
100 #if defined(__SSE4_2__) && !defined(JPL_USE_SSE4_2)
101 #define JPL_USE_SSE4_2
102 #endif
103
104 #if defined(__SSE4_1__) && !defined(JPL_USE_SSE4_1)
105 #define JPL_USE_SSE4_1
106 #endif
107
108 #if !defined(JPL_CROSS_PLATFORM_DETERMINISTIC) // FMA is not compatible with cross platform determinism
109 #if defined(JPL_COMPILER_CLANG) || defined(JPL_COMPILER_GCC)
110 #if defined(__FMA__) && !defined(JPL_USE_FMADD)
111 #define JPL_USE_FMADD
112 #endif
113 #elif defined(JPL_COMPILER_MSVC)
114 #if defined(__AVX2__) && !defined(JPL_USE_FMADD) // AVX2 also enables fused multiply add
115 #define JPL_USE_FMADD
116 #endif
117 #else
118 #error Undefined compiler
119 #endif
120 #endif
121 #endif
122
123 // Cross platform deterministic mode is not yet integrated, or needed,
124 // for now we just error out if the user tries to enable it with FMA
125 #if defined(JPL_CROSS_PLATFORM_DETERMINISTIC) && defined(JPL_USE_FMADD)
126 #error "FMA is incompatible with cross-platform deterministic mode"
127 #endif
128
129 // Normalize the feature hierarchy regardless of whether it came from
130 // CMake or compiler detection
131 #if defined(JPL_USE_AVX512) && !defined(JPL_USE_AVX2)
132 #define JPL_USE_AVX2
133 #endif
134
135 #if defined(JPL_USE_AVX2) && !defined(JPL_USE_AVX)
136 #define JPL_USE_AVX
137 #endif
138
139 #if defined(JPL_USE_AVX) && !defined(JPL_USE_SSE4_2)
140 #define JPL_USE_SSE4_2
141 #endif
142
143 #if defined(JPL_USE_SSE4_2) && !defined(JPL_USE_SSE4_1)
144 #define JPL_USE_SSE4_1
145 #endif
146
147#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
148 //==========================================================================
149 // ARM CPU architecture
150 #define JPL_CPU_ARM
151 #if defined(__aarch64__) || defined(_M_ARM64)
152 #define JPL_CPU_ADDRESS_BITS 64
153 #define JPL_USE_NEON
154 #define JPL_VECTOR_ALIGNMENT 16
155 #define JPL_DVECTOR_ALIGNMENT 32
156 #else
157 #error ""32-bit Arm is not supported""
158 #define JPL_CPU_ADDRESS_BITS 32
159 #define JPL_VECTOR_ALIGNMENT 8 // 32-bit ARM does not support aligning on the stack on 16 byte boundaries
160 #define JPL_DVECTOR_ALIGNMENT 8
161 #endif
162
163#elif defined(JPL_PLATFORM_WASM)
164 //==========================================================================
165 // WebAssembly CPU architecture
166 #define JPL_CPU_WASM
167 #define JPL_CPU_ADDRESS_BITS 32
168 #define JPL_VECTOR_ALIGNMENT 16
169 #define JPL_DVECTOR_ALIGNMENT 32
170 #ifdef __wasm_simd128__
171 #define JPL_USE_SSE
172 #define JPL_USE_SSE4_1
173 #define JPL_USE_SSE4_2
174 #endif
175
176#elif defined(__e2k__)
177 //==========================================================================
178 // Elbrus e2k architecture
179 #define JPL_CPU_E2K
180 #define JPL_CPU_ADDRESS_BITS 64
181 #define JPL_USE_SSE
182 #define JPL_VECTOR_ALIGNMENT 16
183 #define JPL_DVECTOR_ALIGNMENT 32
184
185#else
186 #error Unsupported CPU architecture
187#endif
188
189//==============================================================================
190// OS-specific includes
191#if defined(JPL_PLATFORM_WINDOWS)
192 #define JPL_BREAKPOINT __debugbreak()
193#elif defined(JPL_PLATFORM_LINUX) || defined(JPL_PLATFORM_ANDROID) || defined(JPL_PLATFORM_MACOS) || defined(JPL_PLATFORM_IOS) || defined(JPL_PLATFORM_FREEBSD)
194 #if defined(JPL_CPU_X86)
195 #define JPL_BREAKPOINT __asm volatile ("int $0x3")
196 #elif defined(JPL_CPU_ARM)
197 #define JPL_BREAKPOINT __builtin_trap()
198 #elif defined(JPL_CPU_E2K)
199 #define JPL_BREAKPOINT __builtin_trap()
200 #endif
201#elif defined(JPL_PLATFORM_WASM)
202 #define JPL_BREAKPOINT do { } while (false) // Not supported
203#else
204 #error Unknown platform
205#endif
206
207//==============================================================================
208// If this define is set, JPL is compiled as a shared library
209#ifdef JPL_SHARED_LIBRARY
210 #ifdef JPL_BUILD_SHARED_LIBRARY
211 // While building the shared library, we must export these symbols
212 #ifdef JPL_PLATFORM_WINDOWS
213 #define JPL_EXPORT __declspec(dllexport)
214 #else
215 #define JPL_EXPORT __attribute__ ((visibility ("default")))
216 #if defined(JPL_COMPILER_GCC)
217 // Prevents an issue with GCC attribute parsing (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69585)
218 #define JPL_EXPORT_GCC_BUG_WORKAROUND [[gnu::visibility("default")]]
219 #endif
220 #endif
221 #else
222 // When linking against JPL, we must import these symbols
223 #ifdef JPL_PLATFORM_WINDOWS
224 #define JPL_EXPORT __declspec(dllimport)
225 #else
226 #define JPL_EXPORT __attribute__ ((visibility ("default")))
227 #if defined(JPL_COMPILER_GCC)
228 // Prevents an issue with GCC attribute parsing (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69585)
229 #define JPL_EXPORT_GCC_BUG_WORKAROUND [[gnu::visibility("default")]]
230 #endif
231 #endif
232 #endif
233#else
234 // If the define is not set, we use static linking and symbols don't need to be imported or exported
235 #define JPL_EXPORT
236#endif
237
238#ifndef JPL_EXPORT_GCC_BUG_WORKAROUND
239 #define JPL_EXPORT_GCC_BUG_WORKAROUND JPL_EXPORT
240#endif
241
242//==============================================================================
243#if (defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__)
244 #define JPL_LITTLE_ENDIAN 0
245 #define JPL_BIG_ENDIAN 1
246#else
247 #define JPL_LITTLE_ENDIAN 1
248 #define JPL_BIG_ENDIAN 0
249#endif
250
251// Macro used by the RTTI macros to not export a function
252#define JPL_NO_EXPORT
253
254//==============================================================================
255// Pragmas to store / restore the warning state and to disable individual warnings
256#ifdef JPL_COMPILER_CLANG
257 #define JPL_PRAGMA(x) _Pragma(#x)
258 #define JPL_SUPPRESS_WARNING_PUSH JPL_PRAGMA(clang diagnostic push)
259 #define JPL_SUPPRESS_WARNING_POP JPL_PRAGMA(clang diagnostic pop)
260 #define JPL_CLANG_SUPPRESS_WARNING(w) JPL_PRAGMA(clang diagnostic ignored w)
261 #if __clang_major__ >= 13
262 #define JPL_CLANG_13_PLUS_SUPPRESS_WARNING(w) JPL_CLANG_SUPPRESS_WARNING(w)
263 #else
264 #define JPL_CLANG_13_PLUS_SUPPRESS_WARNING(w)
265 #endif
266 #if __clang_major__ >= 16
267 #define JPL_CLANG_16_PLUS_SUPPRESS_WARNING(w) JPL_CLANG_SUPPRESS_WARNING(w)
268 #else
269 #define JPL_CLANG_16_PLUS_SUPPRESS_WARNING(w)
270 #endif
271#else
272 #define JPL_CLANG_SUPPRESS_WARNING(w)
273 #define JPL_CLANG_13_PLUS_SUPPRESS_WARNING(w)
274 #define JPL_CLANG_16_PLUS_SUPPRESS_WARNING(w)
275#endif
276
277#ifdef JPL_COMPILER_GCC
278 #define JPL_PRAGMA(x) _Pragma(#x)
279 #define JPL_SUPPRESS_WARNING_PUSH JPL_PRAGMA(GCC diagnostic push)
280 #define JPL_SUPPRESS_WARNING_POP JPL_PRAGMA(GCC diagnostic pop)
281 #define JPL_GCC_SUPPRESS_WARNING(w) JPL_PRAGMA(GCC diagnostic ignored w)
282#else
283 #define JPL_GCC_SUPPRESS_WARNING(w)
284#endif
285
286#ifdef JPL_COMPILER_MSVC
287 #define JPL_PRAGMA(x) __pragma(x)
288 #define JPL_SUPPRESS_WARNING_PUSH JPL_PRAGMA(warning (push))
289 #define JPL_SUPPRESS_WARNING_POP JPL_PRAGMA(warning (pop))
290 #define JPL_MSVC_SUPPRESS_WARNING(w) JPL_PRAGMA(warning (disable : w))
291 #if _MSC_VER >= 1920 && _MSC_VER < 1930
292 #define JPL_MSVC2019_SUPPRESS_WARNING(w) JPL_MSVC_SUPPRESS_WARNING(w)
293 #else
294 #define JPL_MSVC2019_SUPPRESS_WARNING(w)
295 #endif
296#else
297 #define JPL_MSVC_SUPPRESS_WARNING(w)
298 #define JPL_MSVC2019_SUPPRESS_WARNING(w)
299#endif
300
301//==============================================================================
302#include <cstdint>
303
304namespace JPL
305{
306
307 // Standard types
308 using uint = unsigned int;
309 using uint8 = std::uint8_t;
310 using uint16 = std::uint16_t;
311 using uint32 = std::uint32_t;
312 using uint64 = std::uint64_t;
313
314 using int8 = std::int8_t;
315 using int16 = std::int16_t;
316 using int32 = std::int32_t;
317 using int64 = std::int64_t;
318
319 // Assert sizes of types
320 static_assert(sizeof(uint) >= 4, "Invalid size of uint");
321 static_assert(sizeof(uint8) == 1, "Invalid size of uint8");
322 static_assert(sizeof(uint16) == 2, "Invalid size of uint16");
323 static_assert(sizeof(uint32) == 4, "Invalid size of uint32");
324 static_assert(sizeof(uint64) == 8, "Invalid size of uint64");
325 static_assert(sizeof(void*) == (JPL_CPU_ADDRESS_BITS == 64 ? 8 : 4), "Invalid size of pointer");
326
327// Determine if we want extra debugging code to be active
328#if !defined(NDEBUG) && !defined(JPL_NO_DEBUG)
329 #define JPL_DEBUG
330#endif
331
332 // Define inline macro
333#if defined(JPL_NO_FORCE_INLINE)
334 #define JPL_INLINE inline
335#elif defined(JPL_COMPILER_CLANG) || defined(JPL_COMPILER_GCC)
336 #define JPL_INLINE __inline__ __attribute__((always_inline))
337#elif defined(JPL_COMPILER_MSVC)
338 #define JPL_INLINE __forceinline
339#else
340 #error Undefined
341#endif
342
343#if defined(JPL_COMPILER_MSVC)
344 #define JPL_NOINLINE __declspec(noinline)
345#elif defined(JPL_COMPILER_CLANG) || defined(JPL_COMPILER_GCC)
346 #define JPL_NOINLINE __attribute__((noinline))
347#else
348 // Fallback for other compilers, which does nothing
349 #define JPL_NOINLINE
350#endif
351
352// Cache line size (used for aligning to cache line)
353#ifndef JPL_CACHE_LINE_SIZE
354 #define JPL_CACHE_LINE_SIZE 64
355#endif
356
357#define JPL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__
358
359#define JPL_BIT(x) (1u << x)
360
361} // namespace JPL
362
363#endif // JPL_CORE_DEFINED
Definition AcousticMaterial.h:36
std::int32_t int32
Definition Core.h:316
std::int8_t int8
Definition Core.h:314
std::uint64_t uint64
Definition Core.h:312
unsigned int uint
Definition Core.h:308
std::uint32_t uint32
Definition Core.h:311
std::uint16_t uint16
Definition Core.h:310
std::int64_t int64
Definition Core.h:317
std::uint8_t uint8
Definition Core.h:309
std::int16_t int16
Definition Core.h:315
JPL_INLINE simd min(const simd &a, const simd &b) noexcept
Element-wise min.
Definition SIMD.h:1813