Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F631482
random.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
3 KB
Referenced Files
None
Subscribers
None
random.cpp
View Options
#include
<random>
#include
"threads.h"
#include
<time.h>
#include
"constants.h"
#include
"vec3.h"
#include
"vec2.h"
#include
"main/references.h"
#include
"os/driver.h"
#include
"random.h"
#if defined(_MSC_VER)
#include
<intrin.h>
#define GET_MSB(var, x) do{ unsigned long _index_; _BitScanReverse(&_index_, x); var = _index_ + 1; } while(false)
#elif defined(__GNUC__)
#define GET_MSB(var, x) do { var = (32 - __builtin_clz(x)); } while(false)
#else
unsigned
_get_msb
(
unsigned
v
)
{
unsigned
index
=
0
;
while
((
1
<<
index
)
<=
v
)
++
index
;
return
index
;
}
#define GET_MSB(var, x) do { var = _get_msb(x); } while(false)
#endif
Threaded
(
std
::
mt19937
*
)
engine
;
void
seed
(
unsigned
long
seed
);
void
initRandomizer
()
{
engine
=
new
std
::
mt19937
();
seed
((
unsigned
long
)
time
(
0
)
^
(
unsigned
long
)
threads
::
getThreadID
());
}
void
freeRandomizer
()
{
delete
engine
;
}
void
seed
(
unsigned
long
seed
)
{
engine
->
seed
(
seed
);
}
unsigned
sysRandomi
()
{
unsigned
ret
=
0
;
if
(
!
devices
.
driver
->
systemRandom
((
unsigned
char
*
)
&
ret
,
4
))
{
if
(
engine
)
ret
=
(
unsigned
)
randomi
();
else
{
initRandomizer
();
ret
=
(
unsigned
)
randomi
();
freeRandomizer
();
}
}
return
ret
;
}
double
randomd
()
{
//Choose random numbers until we don't get max
unsigned
m
=
engine
->
max
();
unsigned
r
;
do
{
r
=
(
*
engine
)();
}
while
(
r
==
m
);
return
(
double
)
r
/
(
double
)
m
;
}
double
randomd
(
double
min
,
double
max
)
{
return
randomd
()
*
(
max
-
min
)
+
min
;
}
double
normald
(
double
min
,
double
max
,
int
steps
)
{
double
sum
=
0
;
for
(
int
i
=
0
;
i
<
steps
;
++
i
)
sum
+=
randomd
();
return
min
+
(
max
-
min
)
*
sum
/
(
double
)
steps
;
}
float
randomf
()
{
return
(
float
)
randomd
();
}
float
randomf
(
float
min
,
float
max
)
{
return
(
float
)(
randomd
()
*
(
double
)(
max
-
min
))
+
min
;
}
unsigned
randomi
()
{
return
(
*
engine
)();
}
int
randomi
(
int
min
,
int
max
)
{
unsigned
range
=
(
unsigned
)
max
-
(
unsigned
)
min
;
if
(
range
==
0
)
return
min
;
unsigned
msb
;
GET_MSB
(
msb
,
range
);
unsigned
mask
=
0xffffffff
>>
(
32
-
msb
);
//Choose uniformly distributed values until one falls into our range
//Worst case scenario is the possible values is split in half (+1), so it will still resolve quickly
unsigned
r
;
do
{
r
=
(
unsigned
)((
*
engine
)());
}
while
((
r
&
mask
)
>
range
);
return
min
+
(
r
&
mask
);
}
vec3d
random3d
(
double
radius
)
{
double
theta
=
randomd
(
0
,
twopi
);
double
u
=
randomd
(
-1.0
,
1.0
);
double
s
=
sqrt
(
1.0
-
(
u
*
u
));
vec3d
out
;
out
.
x
=
s
*
cos
(
theta
)
*
radius
;
out
.
y
=
s
*
sin
(
theta
)
*
radius
;
out
.
z
=
u
*
radius
;
return
out
;
}
vec3d
random3d
(
double
minRadius
,
double
maxRadius
)
{
return
random3d
(
minRadius
+
(
maxRadius
-
minRadius
)
*
sqrt
(
randomd
()));
}
vec2d
random2d
(
double
radius
)
{
double
theta
=
randomd
(
0
,
twopi
);
return
vec2d
(
radius
*
cos
(
theta
),
radius
*
sin
(
theta
));
}
vec2d
random2d
(
double
minRadius
,
double
maxRadius
)
{
return
random2d
(
minRadius
+
(
maxRadius
-
minRadius
)
*
sqrt
(
randomd
()));
}
class
MersenneEngine
:
public
RandomEngine
{
std
::
mt19937
rnd
;
public
:
void
seed
(
unsigned
initial
)
{
rnd
.
seed
((
unsigned
long
)
initial
);
}
unsigned
randomi
()
{
return
rnd
();
}
unsigned
randomi
(
unsigned
min
,
unsigned
max
)
{
unsigned
range
=
(
unsigned
)
max
-
(
unsigned
)
min
;
if
(
range
==
0
)
return
min
;
unsigned
msb
;
GET_MSB
(
msb
,
range
);
unsigned
mask
=
0xffffffff
>>
(
32
-
msb
);
//Choose uniformly distributed values until one falls into our range
//Worst case scenario is the possible values is split in half (+1), so it will still resolve quickly
unsigned
r
;
do
{
r
=
(
unsigned
)(
rnd
());
}
while
((
r
&
mask
)
>
range
);
return
min
+
(
r
&
mask
);
}
double
randomd
()
{
unsigned
m
=
rnd
.
max
();
unsigned
r
;
do
{
r
=
rnd
();
}
while
(
r
==
m
);
return
(
double
)
r
/
(
double
)
m
;
}
double
randomd
(
double
min
,
double
max
)
{
return
(
randomd
()
*
(
max
-
min
))
+
min
;
}
};
RandomEngine
*
RandomEngine::makeMersenne
(
unsigned
seed
)
{
auto
*
engine
=
new
MersenneEngine
();
engine
->
seed
(
seed
);
return
engine
;
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Nov 15, 12:04 PM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
128349
Default Alt Text
random.cpp (3 KB)
Attached To
Mode
R80 StarRuler2-Source
Attached
Detach File
Event Timeline