Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/psx/octoshock/math_ops.h
2 views
1
#pragma once
2
3
#include <intrin.h>
4
5
//
6
// Result is defined for all possible inputs(including 0).
7
//
8
static INLINE unsigned MDFN_lzcount32(uint32 v)
9
{
10
#if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER)
11
return v ? __builtin_clz(v) : 32;
12
#elif defined(_MSC_VER) && defined(_WIN64)
13
unsigned long idx;
14
15
if(!v)
16
return 32;
17
18
_BitScanReverse(&idx, v);
19
20
return 31 - idx;
21
#else
22
unsigned ret = 0;
23
24
if(!v)
25
return(32);
26
27
if(!(v & 0xFFFF0000))
28
{
29
v <<= 16;
30
ret += 16;
31
}
32
33
if(!(v & 0xFF000000))
34
{
35
v <<= 8;
36
ret += 8;
37
}
38
39
if(!(v & 0xF0000000))
40
{
41
v <<= 4;
42
ret += 4;
43
}
44
45
if(!(v & 0xC0000000))
46
{
47
v <<= 2;
48
ret += 2;
49
}
50
51
if(!(v & 0x80000000))
52
{
53
v <<= 1;
54
ret += 1;
55
}
56
57
return(ret);
58
#endif
59
}
60
61
//
62
// Result is defined for all possible inputs(including 0).
63
//
64
static INLINE unsigned MDFN_lzcount64(uint64 v)
65
{
66
#if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER)
67
return v ? __builtin_clzll(v) : 64;
68
#elif defined(_MSC_VER) && defined(_WIN64)
69
unsigned long idx;
70
71
if(!v)
72
return 64;
73
74
_BitScanReverse64(&idx, v);
75
76
return 63 - idx;
77
#else
78
unsigned ret = 0;
79
80
if(!(v & 0xFFFFFFFFFFFFFFFFULL))
81
return(64);
82
83
if(!(v & 0xFFFFFFFF00000000ULL))
84
{
85
v <<= 32;
86
ret += 32;
87
}
88
89
if(!(v & 0xFFFF000000000000ULL))
90
{
91
v <<= 16;
92
ret += 16;
93
}
94
95
if(!(v & 0xFF00000000000000ULL))
96
{
97
v <<= 8;
98
ret += 8;
99
}
100
101
if(!(v & 0xF000000000000000ULL))
102
{
103
v <<= 4;
104
ret += 4;
105
}
106
107
if(!(v & 0xC000000000000000ULL))
108
{
109
v <<= 2;
110
ret += 2;
111
}
112
113
if(!(v & 0x8000000000000000ULL))
114
{
115
v <<= 1;
116
ret += 1;
117
}
118
119
return(ret);
120
#endif
121
}
122
123
124
// Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
125
// Rounds up to the nearest power of 2.
126
static INLINE uint64 round_up_pow2(uint64 v)
127
{
128
v--;
129
v |= v >> 1;
130
v |= v >> 2;
131
v |= v >> 4;
132
v |= v >> 8;
133
v |= v >> 16;
134
v |= v >> 32;
135
v++;
136
137
v += (v == 0);
138
139
return(v);
140
}
141
142
static INLINE uint32 uilog2(uint32 v)
143
{
144
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
145
146
static const uint32 MultiplyDeBruijnBitPosition[32] =
147
{
148
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
149
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
150
};
151
152
v |= v >> 1; // first round down to one less than a power of 2
153
v |= v >> 2;
154
v |= v >> 4;
155
v |= v >> 8;
156
v |= v >> 16;
157
158
return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
159
}
160
161
// Some compilers' optimizers and some platforms might fubar the generated code from these macros,
162
// so some tests are run in...tests.cpp
163
#define sign_8_to_s16(_value) ((int16)(int8)(_value))
164
#define sign_9_to_s16(_value) (((int16)((unsigned int)(_value) << 7)) >> 7)
165
#define sign_10_to_s16(_value) (((int16)((uint32)(_value) << 6)) >> 6)
166
#define sign_11_to_s16(_value) (((int16)((uint32)(_value) << 5)) >> 5)
167
#define sign_12_to_s16(_value) (((int16)((uint32)(_value) << 4)) >> 4)
168
#define sign_13_to_s16(_value) (((int16)((uint32)(_value) << 3)) >> 3)
169
#define sign_14_to_s16(_value) (((int16)((uint32)(_value) << 2)) >> 2)
170
#define sign_15_to_s16(_value) (((int16)((uint32)(_value) << 1)) >> 1)
171
172
// This obviously won't convert higher-than-32 bit numbers to signed 32-bit ;)
173
// Also, this shouldn't be used for 8-bit and 16-bit signed numbers, since you can
174
// convert those faster with typecasts...
175
#define sign_x_to_s32(_bits, _value) (((int32)((uint32)(_value) << (32 - _bits))) >> (32 - _bits))
176
177
static INLINE int32 clamp_to_u8(int32 i)
178
{
179
if(i & 0xFFFFFF00)
180
i = (((~i) >> 30) & 0xFF);
181
182
return(i);
183
}
184
185
static INLINE int32 clamp_to_u16(int32 i)
186
{
187
if(i & 0xFFFF0000)
188
i = (((~i) >> 31) & 0xFFFF);
189
190
return(i);
191
}
192
193
template<typename T, typename U, typename V> static INLINE void clamp(T *val, U minimum, V maximum)
194
{
195
if(*val < minimum)
196
{
197
//printf("Warning: clamping to minimum(%d)\n", (int)minimum);
198
*val = minimum;
199
}
200
if(*val > maximum)
201
{
202
//printf("Warning: clamping to maximum(%d)\n", (int)maximum);
203
*val = maximum;
204
}
205
}
206
207