This is nuts-and-bolt post. We’re going to assume we have the following provided function:

• uint64_t rng_u64() which returns a 64-bit uniform random integer

Let’s first walk though the standard method which produces uniform values on $\left[0,1\right)$. If we were to simply take our 64-bit integer and convert into a float then we’d introduce a bias. So instead we limit ourselves to the largest consecutive sequence of integers that are representable and the length of which is a power-of-two: $\left[0,2^p-1\right)$ where $p$ is the number of precision bits of the format.

and to get our desired range we simply scale the output:

Which completes the standard method of generation (which I refer to as the equidistant method since that’s how samples are spaced). There are a number of ways that we can flip output to $\left(0,1\right]$ but let’s just show one:

So we’re simply shifting all the samples up by one position. The FMA is not required. However it keeps the operation count the same as the standard method (and the same latency if FMAs and products are the same).

When we need base uniform result on $\left[-1,1\right)$ a common method is to use the standard method to generate $u$ and then transform by $2u-1$. We can instead follow the exact same path as the methods above except start with a signed integer. This results in proceedures that have the same runtime cost and (as an added bonus) twice the number of output samples.