util: introduce kernel utils for pseudorandom number generation

Currently there are two generators. The fast one is the same one the scheduler
is using. The standard one is the same algorithm libroot's rand() uses. Should
there be a need for more cryptographically PRNG MD4 or MD5 might be a good
candidates.
This commit is contained in:
Pawel Dziepak 2013-04-11 04:22:22 +02:00
parent feae2b5a00
commit 6003243ef3
3 changed files with 124 additions and 0 deletions

View File

@ -0,0 +1,69 @@
/*
* Copyright 2013 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, pdziepak@quarnos.org
*/
#ifndef KERNEL_UTIL_RANDOM_H
#define KERNEL_UTIL_RANDOM_H
#include <smp.h>
#include <SupportDefs.h>
#define MAX_FAST_RANDOM_VALUE 0x7fff
#define MAX_RANDOM_VALUE 0x7fffffffu
const int kFastRandomShift = 15;
const int kRandomShift = 31;
#ifdef __cplusplus
extern "C" {
#endif
unsigned int fast_random_value(void);
unsigned int random_value(void);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
template<typename T>
T
fast_get_random()
{
size_t shift = 0;
T random = 0;
while (shift < sizeof(T) * 8) {
random |= (T)fast_random_value() << shift;
shift += kFastRandomShift;
}
return random;
}
template<typename T>
T
get_random()
{
size_t shift = 0;
T random = 0;
while (shift < sizeof(T) * 8) {
random |= (T)random_value() << shift;
shift += kRandomShift;
}
return random;
}
#endif // __cplusplus
#endif // KERNEL_UTIL_RANDOM_H

View File

@ -14,6 +14,7 @@ KernelMergeObject kernel_util.o :
queue.cpp
ring_buffer.cpp
RadixBitmap.cpp
Random.cpp
: $(TARGET_KERNEL_PIC_CCFLAGS) -DUSING_LIBGCC
;

View File

@ -0,0 +1,54 @@
/*
* Copyright 2013 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, pdziepak@quarnos.org
*/
#include <util/Random.h>
#include <OS.h>
static uint32 fast_last = 0;
static uint32 last = 0;
// In the following functions there are race conditions when many threads
// attempt to update static variable last. However, since such conflicts
// are non-deterministic it is not a big problem.
// A simple linear congruential generator
unsigned int
fast_random_value()
{
if (fast_last == 0)
fast_last = system_time();
uint32 random = fast_last * 1103515245 + 12345;
fast_last = random;
return (random >> 16) & 0x7fff;
}
// Taken from "Random number generators: good ones are hard to find",
// Park and Miller, Communications of the ACM, vol. 31, no. 10,
// October 1988, p. 1195.
unsigned int
random_value()
{
if (last == 0)
last = system_time();
uint32 hi = last / 127773;
uint32 lo = last % 127773;
int32 random = 16807 * lo - 2836 * hi;
if (random <= 0)
random += MAX_RANDOM_VALUE;
last = random;
return random % (MAX_RANDOM_VALUE + 1);
}