Not Enough Math
Lightweight zero-dependency C++ math library
Loading...
Searching...
No Matches
intrinsics.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <type_traits>
5
6#if defined(_MSC_VER)
7 #include <intrin.h>
8 #include <math.h>
9#endif
10
11// implements compiler/platform specific low-level instructions that are then used in the API. Uses compiler-specific
12// builtins, SIMD instrinsics or standard math inlinement to avoid dependencies.
13// MSVC implementation isn't worked on as much as Clang/GCC are, so issues with it may be overseen. It is tested in
14// CI/CD however.
15// This code was written by me and later restructured by Anthropic Claude and until fully tested and refactored may contain artifacts.
16
17namespace nem
18{
19 namespace intr
20 {
21#if defined(__clang__) || defined(__GNUC__)
22 #define NEM_TRAP() __builtin_trap()
23 #ifdef _DEBUG
24 #define NEM_UNREACHABLE() NEM_TRAP()
25 #else
26 #define NEM_UNREACHABLE() __builtin_unreachable()
27 #endif
28
29#elif defined(_MSC_VER)
30 #define NEM_TRAP() __debugbreak()
31 #define NEM_UNREACHABLE() __assume(0)
32
33#else
34 #error "Unsupported compiler"
35#endif
36
37#if defined(__clang__) || defined(__GNUC__)
38 template <std::floating_point T>
39 T _nem_sqrt(T x) noexcept
40 {
41 if constexpr (std::is_same_v<T, float>)
42 {
43 return __builtin_sqrtf(x);
44 }
45 else if constexpr (std::is_same_v<T, double>)
46 {
47 return __builtin_sqrt(x);
48 }
49 else
50 {
51 return __builtin_sqrtl(x);
52 }
53 }
54
55#elif defined(_MSC_VER)
56 template <std::floating_point T>
57 T _nem_sqrt(T x) noexcept
58 {
59 if constexpr (std::is_same_v<T, float>)
60 {
61 return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(x)));
62 }
63 else if constexpr (std::is_same_v<T, double>)
64 {
65 return ::sqrt(x);
66 }
67 else
68 {
69 return ::sqrtl(x);
70 }
71 }
72#endif
73
74#if defined(__clang__) || defined(__GNUC__)
75 template <std::floating_point T>
76 constexpr T _nem_fabs(T x) noexcept
77 {
78 if constexpr (std::is_same_v<T, float>)
79 {
80 return __builtin_fabsf(x);
81 }
82 else if constexpr (std::is_same_v<T, double>)
83 {
84 return __builtin_fabs(x);
85 }
86 else
87 {
88 return __builtin_fabsl(x);
89 }
90 }
91
92#elif defined(_MSC_VER)
93 template <std::floating_point T>
94 T _nem_fabs(T x) noexcept
95 {
96 if constexpr (std::is_same_v<T, float>)
97 {
98 return ::fabsf(x);
99 }
100 else if constexpr (std::is_same_v<T, double>)
101 {
102 return ::fabs(x);
103 }
104 else
105 {
106 return ::fabsl(x);
107 }
108 }
109#endif
110
111 template <std::floating_point T> bool _nem_isnan(T x) noexcept { return x != x; }
112 template <std::integral T> bool _nem_isnan(T) noexcept { return false; }
113
114 template <std::floating_point T>
115 bool _nem_isfinite(T x) noexcept
116 {
117 return (x == x) && (x - x == T{0});
118 }
119 template <std::integral T> bool _nem_isfinite(T) noexcept { return true; }
120
121#if defined(__clang__) || defined(__GNUC__)
122 template <typename T>
123 constexpr T _nem_copysign(T to, T from) noexcept
124 {
125 if constexpr (std::is_same_v<T, float>)
126 {
127 return __builtin_copysignf(to, from);
128 }
129 else if constexpr (std::is_same_v<T, double>)
130 {
131 return __builtin_copysign(to, from);
132 }
133 else if constexpr (std::is_same_v<T, long double>)
134 {
135 return __builtin_copysignl(to, from);
136 }
137 else if constexpr (std::is_integral_v<T>)
138 {
139 const bool flip = (to < T{0}) ^ (from < T{0});
140 return flip ? -to : to;
141 }
142 else
143 {
144 NEM_UNREACHABLE();
145 }
146 }
147
148#elif defined(_MSC_VER)
149 template <typename T>
150 T _nem_copysign(T to, T from) noexcept
151 {
152 if constexpr (std::is_same_v<T, float>)
153 {
154 return ::copysignf(to, from);
155 }
156 else if constexpr (std::is_same_v<T, double>)
157 {
158 return ::copysign(to, from);
159 }
160 else if constexpr (std::is_same_v<T, long double>)
161 {
162 return ::copysignl(to, from);
163 }
164 else if constexpr (std::is_integral_v<T>)
165 {
166 const bool flip = (to < T{0}) ^ (from < T{0});
167 return flip ? -to : to;
168 }
169 else { NEM_UNREACHABLE(); }
170 }
171#endif
172
173 } // namespace intr
174} // namespace nem
bool _nem_isnan(T x) noexcept
bool _nem_isfinite(T x) noexcept
Definition config.hpp:16