Some definitions to help in the explanation

Floor operation

https://en.wikipedia.org/wiki/Floor_and_ceiling_functions

Greatest integer less than or equal to a real number.
Bitwise Logical shift operators (c-inspired)

https://en.wikipedia.org/wiki/Bitwise_operation#Bit_shifts

Binary bits of value shifted left or right, with zero bits shifted in where appropriate. 
Examples are shown for 8 bit binary numbers; most significant bit to the left.
 << Logical shift left by given number of bits.
E.g Binary 00110101 << 2 == Binary 11010100
 >> Logical shift right by given number of bits.
E.g Binary 00110101 >> 2 == Binary 00001101
^ Bitwise exclusive-or operator
https://en.wikipedia.org/wiki/Exclusive_or
Bitwise comparison for if bits differ
E.g Binary 00110101 ^ Binary 00110011 == Binary 00000110
| Bitwise or operator
https://en.wikipedia.org/wiki/Bitwise_operation#OR
Bitwise comparison gives 1 if any of corresponding bits are 1
E.g Binary 00110101 | Binary 00110011 == Binary 00110111


PCG32 Generator (pseudo-code)

PCG32 has two unsigned 64-bit integers of internal state:

 state: All 2**64 values may be attained.
 sequence: Determines which of 2**63 sequences that state iterates through. (Once set together with state at time of seeding will stay constant for this generators lifetime).
Values of sequence allow 2**63 different sequences of random numbers from the same state.

The algorithm is given 2 U64 inputs called seed_state, and seed_sequence. The algorithm proceeds in accordance with the following pseudocode:-

const N<-U64 6364136223846793005
const inc<-U64 (seed_sequence << 1) | 1
state<-U64 ((inc+seed_state)*N+inc
do forever
  xs<-U32 (((state>>18)^state)>>27)
  rot<-INT (state>>59)
  OUTPUT U32 (xs>>rot)|(xs<<((-rot)&31))
  state<-state*N+inc
end do

Note that this an anamorphism – dual to catamorphism, and encoded in some languages as a general higher-order `unfold` function, dual to `fold` or `reduce`.

Task

 Generate a class/set of functions that generates pseudo-random
numbers using the above.

 Show that the first five integers generated with the seed 42, 54
are: 2707161783 2068313097 3122475824 2211639955 3215226955



 Show that for an initial seed of 987654321, 1 the counts of 100_000 repetitions of
   floor(random_gen.next_float() * 5)

Is as follows:
   0: 20049, 1: 20022, 2: 20115, 3: 19809, 4: 20005

 Show your output here, on this page.


(import (scheme small) (srfi 33))
 
(define PCG-DEFAULT-MULTIPLIER 6364136223846793005)
(define MASK64 (- (arithmetic-shift 1 64) 1))
(define MASK32 (- (arithmetic-shift 1 32) 1))
 
(define-record-type <pcg32-random> (make-pcg32-random-record) pcg32?
  (state pcg32-state pcg32-state!)
  (inc   pcg32-inc   pcg32-inc!))
 
(define (make-pcg32)
  (define rng (make-pcg32-random-record))
  (pcg32-seed rng 31415926 535897932)
  rng)
 
(define (pcg32-seed rng init-state init-seq)
  (pcg32-state! rng 0)
  (pcg32-inc!   rng 
    (bitwise-and 
      (bitwise-ior (arithmetic-shift init-seq 1) 1) 
      MASK64))
  (pcg32-next-int rng)
  (pcg32-state! rng (bitwise-and (+ (pcg32-state rng) init-state) MASK64))
  (pcg32-next-int rng))
 
(define (pcg32-next-int rng)
  (define xorshifted 0)
  (define rot        0)
  (define answer     0) 
  (define oldstate (pcg32-state rng))
  (pcg32-state! rng 
    (bitwise-and 
      (+ (* oldstate PCG-DEFAULT-MULTIPLIER) (pcg32-inc rng)) 
      MASK64))
  (set! xorshifted  (bitwise-xor (arithmetic-shift oldstate -18) oldstate))
  (set! xorshifted  (arithmetic-shift xorshifted -27))
  (set! xorshifted  (bitwise-and xorshifted MASK32))
  (set! rot (bitwise-and (arithmetic-shift oldstate -59) MASK32))
  (set! answer (bitwise-ior
    (arithmetic-shift xorshifted (- rot))
    (arithmetic-shift xorshifted (bitwise-and (- rot) 31))))
  (set! answer (bitwise-and answer MASK32))
  answer)
 
(define (pcg32-next-float rng)
  (inexact (/ (pcg32-next-int rng) (arithmetic-shift 1 32))))
 
;; task
 
(define rng (make-pcg32))
(pcg32-seed rng 42 54)
(let lp ((i 0)) (when (< i 5) 
  (display (pcg32-next-int rng))(newline) 
  (lp (+ i 1))))
(newline)
 
(pcg32-seed rng 987654321 1)
(define vec (make-vector 5 0))
(let lp ((i 0)) (when (< i 100000)
  (let ((j (exact (floor (* (pcg32-next-float rng) 5)))))
    (vector-set! vec j (+ (vector-ref vec j) 1)))
  (lp (+ i 1))))
(let lp ((i 0)) (when (< i 5)
  (display i)
  (display " : ")
  (display (vector-ref vec i))
  (newline)
  (lp (+ i 1))))
 