@@ -603,11 +603,39 @@ end
603
603
604
604
# ### arrays of Bool
605
605
606
- function rand! (r:: MersenneTwister , A:: Array{Bool} , sp:: SamplerType{Bool} )
607
- GC. @preserve A rand! (r,
608
- UnsafeView (Ptr {UInt8} (pointer (A)), length (A)),
609
- SamplerType {UInt8} ())
610
- A
606
+ # similar to Array{UInt8}, but we need to mask the result so that only the LSB
607
+ # in each byte can be non-zero
608
+
609
+ function rand! (r:: MersenneTwister , A1:: Array{Bool} , sp:: SamplerType{Bool} )
610
+ n1 = length (A1)
611
+ n128 = n1 ÷ 16
612
+
613
+ A = UnsafeView {UInt128} (pointer (A1), n128)
614
+ rand! (r, UnsafeView {Float64} (A. ptr, 2 * n128), CloseOpen12 ())
615
+ mask = 0x01010101010101010101010101010101
616
+ # without masking, non-zero bits could be observed in other
617
+ # positions than the LSB of each byte
618
+
619
+ if n128 > 0
620
+ # we need up to 15 bits of entropy for the last loop;
621
+ # A[1] % UInt64 contains 52 bits of entropy, but 8
622
+ # of them will be used for A[i] itself (the first of
623
+ # each byte). To compensate, we xor with (A[1] >> 65),
624
+ # which gets the entropy from the second bit of each byte
625
+ # of the upper-half of A[i].
626
+ bits = (A[1 ] % UInt64) ⊻ (A[1 ] >> 65 ) % UInt64
627
+ else
628
+ bits = rand (r, UInt52Raw ())
629
+ end
630
+ for i = 1 : n128
631
+ # << 5 to initialize the first bit of the 8th byte
632
+ A[i] = (A[i] ⊻ A[i] << 5 ) & mask
633
+ end
634
+ for i = 16 * n128+ 1 : n1
635
+ @inbounds A1[i] = bits % Bool
636
+ bits >>= 1
637
+ end
638
+ A1
611
639
end
612
640
613
641
0 commit comments