@@ -586,8 +586,10 @@ function rand!(r::MersenneTwister, A::UnsafeView{UInt128}, ::SamplerType{UInt128
586
586
end
587
587
588
588
for T in BitInteger_types
589
- @eval rand! (r:: MersenneTwister , A:: Array{$T} , sp:: SamplerType{$T} ) =
590
- (GC. @preserve A rand! (r, UnsafeView (pointer (A), length (A)), sp); A)
589
+ @eval function rand! (r:: MersenneTwister , A:: Array{$T} , sp:: SamplerType{$T} )
590
+ GC. @preserve A rand! (r, UnsafeView (pointer (A), length (A)), sp)
591
+ A
592
+ end
591
593
592
594
T == UInt128 && continue
593
595
@@ -602,6 +604,52 @@ for T in BitInteger_types
602
604
end
603
605
end
604
606
607
+
608
+ # ### arrays of Bool
609
+
610
+ # similar to Array{UInt8}, but we need to mask the result so that only the LSB
611
+ # in each byte can be non-zero
612
+
613
+ function rand! (r:: MersenneTwister , A1:: Array{Bool} , sp:: SamplerType{Bool} )
614
+ n1 = length (A1)
615
+ n128 = n1 ÷ 16
616
+
617
+ if n128 == 0
618
+ bits = rand (r, UInt52Raw ())
619
+ else
620
+ GC. @preserve A1 begin
621
+ A = UnsafeView {UInt128} (pointer (A1), n128)
622
+ rand! (r, UnsafeView {Float64} (A. ptr, 2 * n128), CloseOpen12 ())
623
+ # without masking, non-zero bits could be observed in other
624
+ # positions than the LSB of each byte
625
+ mask = 0x01010101010101010101010101010101
626
+ # we need up to 15 bits of entropy in `bits` for the final loop,
627
+ # which we will extract from x = A[1] % UInt64;
628
+ # let y = x % UInt32; y contains 32 bits of entropy, but 4
629
+ # of them will be used for A[1] itself (the first of
630
+ # each byte). To compensate, we xor with (y >> 17),
631
+ # which gets the entropy from the second bit of each byte
632
+ # of the upper-half of y, and sets it in the first bit
633
+ # of each byte of the lower half; the first two bytes
634
+ # now contain 16 usable random bits
635
+ x = A[1 ] % UInt64
636
+ bits = x ⊻ x >> 17
637
+ for i = 1 : n128
638
+ # << 5 to randomize the first bit of the 8th & 16th byte
639
+ # (i.e. we move bit 52 (resp. 52 + 64), which is unused,
640
+ # to position 57 (resp. 57 + 64))
641
+ A[i] = (A[i] ⊻ A[i] << 5 ) & mask
642
+ end
643
+ end
644
+ end
645
+ for i = 16 * n128+ 1 : n1
646
+ @inbounds A1[i] = bits % Bool
647
+ bits >>= 1
648
+ end
649
+ A1
650
+ end
651
+
652
+
605
653
# ## randjump
606
654
607
655
# Old randjump methods are deprecated, the scalar version is in the Future module.
0 commit comments