Mercurial > octave
changeset 27855:9405e2be91d0
Restrict rand ("single") to range (0, 1) (bug #41742).
* NEWS: Announce change in rand function.
* randmtzig.cc (randu24): Rename function from randu32.
New algorithm uses masking to reduce randi32() to 24-bits.
Test for value of 0 to exclude left endpoint of range.
Divide result by 2^24 which guarantees right endpoint of 1 is excluded.
* randmtzig.cc: Rename all instances of randu32 with randu24.
author | Rik <rik@octave.org> |
---|---|
date | Thu, 19 Dec 2019 11:57:54 -0800 |
parents | a57e88065f89 |
children | b3a03dbde858 |
files | NEWS liboctave/numeric/randmtzig.cc |
diffstat | 2 files changed, 22 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Thu Dec 19 11:29:22 2019 -0800 +++ b/NEWS Thu Dec 19 11:57:54 2019 -0800 @@ -18,6 +18,15 @@ endpoints are symmetric. This is more intuitive and also compatible with recent changes made in Matlab R2019b. +- The underlying algorithm of the `rand` function has been changed. + For single precision outputs, the algorithm has been fixed so that it + produces values strictly in the range (0, 1). Previously, it could + occasionally generate the right endpoint value of 1 (See bug #41742). + In addition, the new implementation uses a uniform interval between + floating point values in the range (0, 1) rather than targeting a + uniform density (# of random integers / length along real number + line). + - The `edit` function option `"editinplace"` now defaults to `true` and the option `"home"` now defaults to the empty matrix `[]`. Files will no longer be copied to the user's HOME directory for editing. The old
--- a/liboctave/numeric/randmtzig.cc Thu Dec 19 11:29:22 2019 -0800 +++ b/liboctave/numeric/randmtzig.cc Thu Dec 19 11:57:54 2019 -0800 @@ -138,7 +138,7 @@ static uint32_t randi32 (void) returns 32-bit unsigned int static uint64_t randi53 (void) returns 53-bit unsigned int static uint64_t randi54 (void) returns 54-bit unsigned int - static float randu32 (void) returns 32-bit uniform in (0,1) + static float randu24 (void) returns 24-bit uniform in (0,1) static double randu53 (void) returns 53-bit uniform in (0,1) double rand_uniform (void) returns M-bit uniform in (0,1) @@ -377,10 +377,17 @@ } /* generates a random number on (0,1)-real-interval */ - static float randu32 (void) + static float randu24 (void) { - return (static_cast<float> (randi32 ()) + 0.5) * (1.0/4294967296.0); - /* divided by 2^32 */ + uint32_t i; + + do + { + i = randi32 () & static_cast<uint32_t> (0xFFFFFF); + } + while (i == 0); + + return i * (1.0f / 16777216.0f); } /* generates a random number on (0,1) with 53-bit resolution */ @@ -404,7 +411,7 @@ float rand_uniform<float> (void) { - return randu32 (); + return randu24 (); } /* ===== Ziggurat normal and exponential generators ===== */ @@ -665,7 +672,7 @@ #define ERANDI randi32() /* 32 bits for mantissa */ #define NMANTISSA 2147483648.0 /* 31 bit mantissa */ #define NRANDI randi32() /* 31 bits for mantissa + 1 bit sign */ -#define RANDU randu32() +#define RANDU randu24() static ZIGINT fki[ZIGGURAT_TABLE_SIZE]; static float fwi[ZIGGURAT_TABLE_SIZE], ffi[ZIGGURAT_TABLE_SIZE];