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
304
namespace
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
JPL
Definition
AcousticMaterial.h:36
JPL::int32
std::int32_t int32
Definition
Core.h:316
JPL::int8
std::int8_t int8
Definition
Core.h:314
JPL::uint64
std::uint64_t uint64
Definition
Core.h:312
JPL::uint
unsigned int uint
Definition
Core.h:308
JPL::uint32
std::uint32_t uint32
Definition
Core.h:311
JPL::uint16
std::uint16_t uint16
Definition
Core.h:310
JPL::int64
std::int64_t int64
Definition
Core.h:317
JPL::uint8
std::uint8_t uint8
Definition
Core.h:309
JPL::int16
std::int16_t int16
Definition
Core.h:315
JPL::min
JPL_INLINE simd min(const simd &a, const simd &b) noexcept
Element-wise min.
Definition
SIMD.h:1813
JPLSpatial
Core.h
Generated by
1.9.8