[swift-evolution] [Proposal] Random Unification

Xiaodi Wu xiaodi.wu at gmail.com
Thu Nov 16 21:35:50 CST 2017

Nate's is an intriguing idea, but I agree here with Alejandro that for
custom generators it'd be very strange to demand that the implementer take
a computed result that will always be some integer and then return a
_pointer_ to it.

And if RandomNumberGenerator conforms to Sequence (I would recommend it, as
it enables some very elegant generic uses, although to improve ergonomics
we would want to allow methods of type () -> T to satisfy requirements of
type () -> T?), next() most definitely cannot be an unsafe API.

On Thu, Nov 16, 2017 at 21:12 Alejandro Alonso <aalonso128 at outlook.com>

> While this could work, I don’t believe this aligns with Swift.
> SecRandomCopyBytes and arc4random_buf do it this way because of the
> languages they were built in, and for SecRandomCopyBytes, it needs to also
> return an error (in the form of its return value). For custom generators
> this doesn’t make sense to me because it seems as if each generator will
> have the same code to return an integer of a different size from what it’ll
> be producing. I really like Xiaodi’s solution to explicitly state what type
> of integer a custom generator will return, and as a default implementation,
> we provide a way to transform that.
> - Alejandro
> On Nov 15, 2017, 11:26 AM -0600, Nate Cook <natecook at apple.com>, wrote:
> On Nov 13, 2017, at 7:38 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Mon, Nov 13, 2017 at 7:12 PM, Alejandro Alonso <aalonso128 at outlook.com>
> wrote:
>> After thinking about this for a while, I don’t agree with with an
>> associated type on RandomNumberGenerator. I think a generic
>> FixedWidthInteger & UnsignedInteger should be sufficient. If there were an
>> associated type, and the default for Random was UInt32, then there might be
>> some arguments about allowing Double to utilize the full 64 bit precision.
>> We could make Random32 and Random64, but I think people will ask why there
>> isn’t a Random8 or Random16 for those bit widths. The same could also be
>> said that any experienced developer would know that his PRNG would be
>> switched if he asked for 32 bit or 64 bit.
> I don't understand. Of course, Double would require 64 bits of randomness.
> It would obtain this by calling `next()` as many times as necessary to
> obtain the requisite number of bits.
> At base, any PRNG algorithm yields some fixed number of bits on each
> iteration. You can certainly have a function that returns an arbitrary
> number of random bits (in fact, I would recommend that such an algorithm be
> a protocol extension method on RandomNumberGenerator), but it must be built
> on top of a function that returns a fixed number of bits, where that number
> is determined on a per-algorithm basis. Moreover--and this is
> important--generating a random unsigned integer of arbitrary bit width in a
> sound way is actually subtly _different_ from generating a floating-point
> value of a certain bit width, and I'm not sure that one can be built on top
> of the other. Compare, for example:
> https://github.com/xwu/NumericAnnex/blob/c962760bf974a84ec57d8c5e94c91f06584e2453/Sources/PRNG.swift#L157
> https://github.com/xwu/NumericAnnex/blob/c962760bf974a84ec57d8c5e94c91f06584e2453/Sources/PRNG.swift#L316
> (These are essentially Swift versions of C++ algorithms.)
> Basically, what I'm saying is that RandomNumberGenerator needs a `next()`
> method that returns a fixed number of bits, and extension methods that
> build on that to return T : FixedWidthInteger & UnsignedInteger of
> arbitrary bit width or U : BinaryFloatingPoint of an arbitrary number of
> bits of precision. Each individual RNG does not need to reimplement the
> latter methods, just a method to return a `next()` value of a fixed number
> of bits. You are welcome to use my implementation.
> An alternative to this is to have the random generator write a specified
> number of bytes to a pointer’s memory, as David Waite and others have
> suggested. This is same way arc4random_buf and SecRandomCopyBytes are
> implemented. Each random number generator could then choose the most
> efficient way to provide the requested number of bytes. The protocol could
> look something like this:
> protocol RandomNumberGenerator {
>     /// Writes the specified number of bytes to the given pointer’s memory.
>     func read(into p: UnsafeMutableRawPointer, bytes: Int)
> }
> This is less user-friendly than having a next() method, but I think that’s
> a good thing—we very much want people who need a random value to use
> higher-level APIs and just pass the RNG as a parameter when necessary.
> Nate
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171117/1429a9e0/attachment.html>

More information about the swift-evolution mailing list