diff --git a/headers/private/kernel/util/Random.h b/headers/private/kernel/util/Random.h new file mode 100644 index 0000000000..7ca4f05312 --- /dev/null +++ b/headers/private/kernel/util/Random.h @@ -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 +#include + + +#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 +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 +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 + diff --git a/src/system/kernel/util/Jamfile b/src/system/kernel/util/Jamfile index 02ce7ce690..a8f49b9d2a 100644 --- a/src/system/kernel/util/Jamfile +++ b/src/system/kernel/util/Jamfile @@ -14,6 +14,7 @@ KernelMergeObject kernel_util.o : queue.cpp ring_buffer.cpp RadixBitmap.cpp + Random.cpp : $(TARGET_KERNEL_PIC_CCFLAGS) -DUSING_LIBGCC ; diff --git a/src/system/kernel/util/Random.cpp b/src/system/kernel/util/Random.cpp new file mode 100644 index 0000000000..417abe7324 --- /dev/null +++ b/src/system/kernel/util/Random.cpp @@ -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 + +#include + + +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); +} +