ReXGlue SDK
Toggle main menu visibility
Loading...
Searching...
No Matches
math.h
Go to the documentation of this file.
1
12
13
#pragma once
14
15
#include <algorithm>
16
#include <bit>
17
#include <cmath>
18
#include <cstdint>
19
#include <cstring>
20
#include <limits>
21
#include <numeric>
22
#include <type_traits>
23
#include <utility>
24
25
#include <
rex/assert.h
>
26
#include <
rex/platform.h
>
27
#include <
rex/types.h
>
28
29
namespace
rex
{
30
31
template
<
typename
T,
size_t
N>
32
constexpr
size_t
CountOf(T (&)[N])
noexcept
{
33
return
std::extent<T[N]>::value;
34
}
35
41
template
<
typename
T>
42
constexpr
T
RoundUpPow2
(T value, T alignment) {
43
return
(value + alignment - 1) & ~(alignment - 1);
44
}
45
51
template
<
typename
T,
typename
V>
52
constexpr
T
RoundUp
(T value, V multiple) {
53
return
(value + multiple - 1) / multiple * multiple;
54
}
55
62
template
<
typename
T,
typename
V>
63
constexpr
T
RoundUpNonZero
(T value, V multiple) {
64
if
(!value) {
65
return
multiple;
66
}
67
return
RoundUp
(value, multiple);
68
}
69
76
template
<
typename
T>
77
T
clamp_float
(T value, T min_value, T max_value) {
78
f32 clamped_to_min = std::isgreater(value, min_value) ? value : min_value;
79
return
std::isless(clamped_to_min, max_value) ? clamped_to_min : max_value;
80
}
81
83
template
<
typename
T>
84
T
saturate
(T value) {
85
return
clamp_float
(value,
static_cast<
T
>
(0.0f),
static_cast<
T
>
(1.0f));
86
}
87
94
template
<
typename
T>
95
constexpr
void
reduce_fraction
(T& numerator, T& denominator) {
96
auto
gcd = std::gcd(numerator, denominator);
97
numerator /= gcd;
98
denominator /= gcd;
99
}
100
106
template
<
typename
T>
107
constexpr
void
reduce_fraction
(std::pair<T, T>& fraction) {
108
reduce_fraction<T>
(fraction.first, fraction.second);
109
}
110
118
constexpr
u64
mul_div
(u64 value, u64 numerator, u64 denominator) {
119
REX_ASSERT
(denominator != 0);
120
constexpr
u64 kMax = std::numeric_limits<u64>::max();
121
constexpr
u64 kHalfMask = 0xFFFFFFFF;
122
if
(denominator == 0) {
123
return
kMax;
124
}
125
const
unsigned
__int128 product =
static_cast<
unsigned
__int128
>
(value) * numerator;
126
u64 high =
static_cast<
u64
>
(product >> 64);
127
u64 low =
static_cast<
u64
>
(product);
128
if
(high >= denominator) {
129
return
kMax;
130
}
131
if
(high == 0) {
132
return
low / denominator;
133
}
134
135
const
int
shift = std::countl_zero(denominator);
136
denominator <<= shift;
137
high = (high << shift) | (shift == 0 ? 0 : low >> (64 - shift));
138
low <<= shift;
139
const
u64 divisor_high = denominator >> 32;
140
const
u64 divisor_low = denominator & kHalfMask;
141
142
const
auto
divide_step = [&](u64 dividend, u64 next_half) {
143
u64 quotient = dividend / divisor_high;
144
u64 remainder = dividend % divisor_high;
145
while
((quotient >> 32) != 0 || quotient * divisor_low > ((remainder << 32) | next_half)) {
146
--quotient;
147
remainder += divisor_high;
148
if
((remainder >> 32) != 0) {
149
break
;
150
}
151
}
152
return
quotient;
153
};
154
155
const
u64 low_high = low >> 32;
156
const
u64 quotient_high = divide_step(high, low_high);
157
const
u64 partial = ((high << 32) | low_high) - quotient_high * denominator;
158
const
u64 quotient_low = divide_step(partial, low & kHalfMask);
159
return
(quotient_high << 32) | quotient_low;
160
}
161
167
template
<
typename
T>
168
inline
T
SatAdd
(T a, T b) {
169
using
TU = std::make_unsigned<T>::type;
170
TU result =
static_cast<
TU
>
(a) +
static_cast<
TU
>
(b);
171
if
(std::is_unsigned<T>::value) {
172
result |=
static_cast<
TU
>
(-
static_cast<
std::make_signed<T>::type
>
(result < static_cast<TU>(a)));
173
}
else
{
174
TU overflowed = (
static_cast<
TU
>
(a) >> (
sizeof
(T) * 8 - 1)) + std::numeric_limits<T>::max();
175
if
(
static_cast<
T
>
((overflowed ^
static_cast<
TU
>
(b)) | ~(
static_cast<
TU
>
(b) ^ result)) >= 0) {
176
result = overflowed;
177
}
178
}
179
return
static_cast<
T
>
(result);
180
}
181
187
template
<
typename
T>
188
inline
T
SatSub
(T a, T b) {
189
using
TU = std::make_unsigned<T>::type;
190
TU result =
static_cast<
TU
>
(a) -
static_cast<
TU
>
(b);
191
if
(std::is_unsigned<T>::value) {
192
result &=
193
static_cast<
TU
>
(-
static_cast<
std::make_signed<T>::type
>
(result <= static_cast<TU>(a)));
194
}
else
{
195
TU overflowed = (
static_cast<
TU
>
(a) >> (
sizeof
(T) * 8 - 1)) + std::numeric_limits<T>::max();
196
if
(
static_cast<
T
>
((overflowed ^
static_cast<
TU
>
(b)) & (overflowed ^ result)) < 0) {
197
result = overflowed;
198
}
199
}
200
return
static_cast<
T
>
(result);
201
}
202
204
struct
Vec2
{
205
f32 x = 0;
206
f32 y = 0;
207
208
constexpr
bool
operator==(
const
Vec2
& other)
const
=
default
;
209
};
210
211
}
// namespace rex
assert.h
REX_ASSERT
#define REX_ASSERT(cond,...)
Definition
assert.h:84
rex
Definition
app.h:36
rex::mul_div
constexpr u64 mul_div(u64 value, u64 numerator, u64 denominator)
Definition
math.h:118
rex::RoundUp
constexpr T RoundUp(T value, V multiple)
Definition
math.h:52
rex::SatSub
T SatSub(T a, T b)
Definition
math.h:188
rex::saturate
T saturate(T value)
Definition
math.h:84
rex::RoundUpPow2
constexpr T RoundUpPow2(T value, T alignment)
Definition
math.h:42
rex::RoundUpNonZero
constexpr T RoundUpNonZero(T value, V multiple)
Definition
math.h:63
rex::SatAdd
T SatAdd(T a, T b)
Definition
math.h:168
rex::clamp_float
T clamp_float(T value, T min_value, T max_value)
Definition
math.h:77
rex::reduce_fraction
constexpr void reduce_fraction(T &numerator, T &denominator)
Definition
math.h:95
platform.h
Platform flags, packing macros and export markers.
rex::Vec2
Definition
math.h:204
types.h
Integer types, byte order wrappers and size literals.
rex
math.h
Generated by
1.18.0