Reduce RandDouble to one call to ldexp, add one bit of precision
Review URL: http://codereview.chromium.org/5801 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2712 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -6,18 +6,11 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace {
|
||||
|
||||
union uint64_splitter {
|
||||
uint64 normal;
|
||||
uint16 split[4];
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace base {
|
||||
|
||||
int RandInt(int min, int max) {
|
||||
@ -31,15 +24,15 @@ int RandInt(int min, int max) {
|
||||
}
|
||||
|
||||
double RandDouble() {
|
||||
uint64_splitter number;
|
||||
number.normal = base::RandUInt64();
|
||||
// We try to get maximum precision by masking out as many bits as will fit
|
||||
// in the target type's mantissa, and raising it to an appropriate power to
|
||||
// produce output in the range [0, 1). For IEEE 754 doubles, the mantissa
|
||||
// is expected to accommodate 53 bits.
|
||||
|
||||
// Standard code based on drand48 would give only 48 bits of precision.
|
||||
// We try to get maximum precision for IEEE 754 double (52 bits).
|
||||
double result = ldexp(static_cast<double>(number.split[0] & 0xf), -52) +
|
||||
ldexp(static_cast<double>(number.split[1]), -48) +
|
||||
ldexp(static_cast<double>(number.split[2]), -32) +
|
||||
ldexp(static_cast<double>(number.split[3]), -16);
|
||||
COMPILE_ASSERT(std::numeric_limits<double>::radix == 2, otherwise_use_scalbn);
|
||||
static const int kBits = std::numeric_limits<double>::digits;
|
||||
uint64 random_bits = base::RandUInt64() & ((GG_UINT64_C(1) << kBits) - 1);
|
||||
double result = ldexp(static_cast<double>(random_bits), -1 * kBits);
|
||||
DCHECK(result >= 0.0 && result < 1.0);
|
||||
return result;
|
||||
}
|
||||
|
@ -20,3 +20,10 @@ TEST(RandUtilTest, SameMinAndMax) {
|
||||
EXPECT_EQ(base::RandInt(kIntMin, kIntMin), kIntMin);
|
||||
EXPECT_EQ(base::RandInt(kIntMax, kIntMax), kIntMax);
|
||||
}
|
||||
|
||||
TEST(RandUtilTest, RandDouble) {
|
||||
// Force 64-bit precision, making sure we're not in a 80-bit FPU register.
|
||||
volatile double number = base::RandDouble();
|
||||
EXPECT_GT(1.0, number);
|
||||
EXPECT_LE(0.0, number);
|
||||
}
|
||||
|
Reference in New Issue
Block a user