user
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:

1. **state**: All 2\*\*64 values may be attained.
2. **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.
assistant
**Works with**: Rakudo version 2020.07

**Translation of**: Python

Or... at least, it started out that way.

Raku does not have unsigned Integers at this time (Integers are arbitrary sized) so use explicit bit masks during bitwise operations.

```
class PCG32 {
    has $!state;
    has $!incr;
    constant mask32 = 2³² - 1;
    constant mask64 = 2⁶⁴ - 1;
    constant const = 6364136223846793005;

    submethod BUILD (
        Int :$seed = 0x853c49e6748fea9b, # default seed
        Int :$incr = 0xda3e39cb94b95bdb  # default increment
      ) {
        $!incr  = $incr +< 1 +| 1 +& mask64;
        $!state = (($!incr + $seed) * const + $!incr) +& mask64;
    }

    method next-int {
        my $shift  = ($!state +> 18 +^ $!state) +> 27 +& mask32;
        my $rotate =  $!state +> 59 +& 31;
        $!state    = ($!state * const + $!incr) +& mask64;
        ($shift +> $rotate) +| ($shift +< (32 - $rotate) +& mask32)
    }

    method next-rat { self.next-int / 2³² }
}


# Test next-int with custom seed and increment
say 'Seed: 42, Increment: 54; first five Int values:';
my $rng = PCG32.new( :seed(42), :incr(54) );
.say for $rng.next-int xx 5;


# Test next-rat (since these are rational numbers by default)
say "\nSeed: 987654321, Increment: 1; first 1e5 Rat values histogram:";
$rng = PCG32.new( :seed(987654321), :incr(1) );
say ( ($rng.next-rat * 5).floor xx 100_000 ).Bag;


# Test next-int with default seed and increment
say "\nSeed: default, Increment: default; first five Int values:";
$rng = PCG32.new;
.say for $rng.next-int xx 5;

```

Output:

```
Seed: 42, Increment: 54; first five Int values:
2707161783
2068313097
3122475824
2211639955
3215226955

Seed: 987654321, Increment: 1; first 1e5 Rat values histogram:
Bag(0(20049), 1(20022), 2(20115), 3(19809), 4(20005))

Seed: default, Increment: default; first five Int values:
465482994
3895364073
1746730475
3759121132
2984354868
```