> On Nov 13, 2017, at 7:38 PM, Xiaodi Wu <[email protected]> wrote:
> 
> On Mon, Nov 13, 2017 at 7:12 PM, Alejandro Alonso <[email protected] 
> <mailto:[email protected]>> 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#L157>
> https://github.com/xwu/NumericAnnex/blob/c962760bf974a84ec57d8c5e94c91f06584e2453/Sources/PRNG.swift#L316
>  
> <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


_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to