<commit_before>module Random.Pcg exposing (Generator, Seed, bool, int, float, oneIn, sample, pair, list, maybe, choice, choices, frequency, map, map2, map3, map4, map5, andMap, filter, constant, andThen, minInt, maxInt, step, generate, initialSeed, independentSeed, fastForward, toJson, fromJson)

{-| Generate psuedo-random numbers and values, by constructing
[generators](#Generator) for them. There are a bunch of basic generators like
[`bool`](#bool) and [`int`](#int) that you can build up into fancier generators
with functions like [`list`](#list) and [`map`](#map).

You run a `Generator` by calling the [`step`](#step) function, which
also takes a random [`Seed`](#Seed), and passes back a new seed. You should
never use the same seed twice because you will get the same result! If you need
random values over time, you should store the most recent seed in your model.
Alternatively, use [`generate`](#generate) to obtain random values from the Elm
runtime.

This is an implementation of [PCG](http://www.pcg-random.org/) by <NAME>,
and is not cryptographically secure.

# Getting Started
@docs initialSeed, step, generate

# Basic Generators
@docs Generator, bool, int, float, oneIn, sample

# Combining Generators
@docs pair, list, maybe, choice, choices, frequency

# Custom Generators
@docs constant, map, map2, map3, map4, map5, andMap, andThen, filter

# Working With Seeds
@docs Seed, independentSeed, fastForward, toJson, fromJson

# Constants
@docs minInt, maxInt
-}

import Bitwise
import Json.Encode
import Json.Decode
import Task
import Time


{-| A `Generator` is like a recipe for generating certain random values. So a
`Generator Int` describes how to generate integers and a `Generator String`
describes how to generate strings.
-}
type Generator a
    = Generator (Seed -> ( a, Seed ))


{-| Generate a random value as specified by a given `Generator`, using a `Seed`
and returning a new one.

In the following example, we are trying to generate numbers between 0 and 100
with the `int 0 100` generator. Each time we call `generate` we need to provide
a seed. This will produce a random number and a *new* seed to use if we want to
run other generators later.

    (x, seed1) = step (int 0 100) seed0
    (y, seed2) = step (int 0 100) seed1
    (z, seed3) = step (int 0 100) seed2
    [x, y, z] -- [85, 0, 38]

Notice that we use different seeds on each line. This is important! If you reuse
the same seed, you get the same results.

    (x, _) = step (int 0 100) seed0
    (y, _) = step (int 0 100) seed0
    (z, _) = step (int 0 100) seed0
    [x,y,z] -- [85, 85, 85]

As you can see, threading seeds through many calls to `step` is tedious and
error-prone. That's why this library includes many functions to build more
complicated generators, allowing you to call `step` only a small number of
times.

Our example is best written as:

    (xs, newSeed) = step (list 3 <| int 0 100) seed0
    xs -- [85, 0, 38]

-}
step : Generator a -> Seed -> ( a, Seed )
step (Generator generator) seed =
    generator seed


{-| Create a Command that will generate random values according to the supplied
`Generator`.

Think of this function as an alternative to `step`, since they both provide a
way to actually get the random values that you want. This function frees you
from worrying about seeds entirely, but as a tradeoff, you get your random
values asynchronously, in their own Message. Additionally, due to constraints on
third-party packages, it's possible that multiple commands sent at the same
moment will return the same values.

You can also think of this function as an alternative to `independentSeed`,
since they both allow you to use randomness in deeply nested components. In the
case of this function, it's through sending Commands up the chain that you have
to set up anyway.
-}
generate : (a -> msg) -> Generator a -> Cmd msg
generate toMsg generator =
    Time.now
        |> Task.map (round >> initialSeed >> step generator >> fst)
        |> Task.perform never toMsg


never : Never -> a
never a =
    never a


{-| A `Seed` is the source of randomness in the whole system. It hides the
current state of the random number generator.

Generators, not seeds, are the primary data structure for generating random
values. Generators are much easier to chain and combine than functions that take
and return seeds. Creating and managing seeds should happen "high up" in your
program.
-}
type Seed
    = Seed Int Int


{-| Initialize the state of the random number generator. The input should be
a randomly chosen 32-bit integer. You can generate and copy random integers to
create a reproducible psuedo-random generator.

    $ node
    > Math.floor(Math.random()*0xFFFFFFFF)
    227852860

    -- Elm
    seed0 : Seed
    seed0 = initialSeed 227852860

Alternatively, you can generate the random integers on page load and pass them
through a port. The program will be different every time.

    -- Elm
    port randomSeed : Int

    seed0 : Seed
    seed0 = initialSeed randomSeed

    -- JS
    Elm.ModuleName.fullscreen(
      { randomSeed: Math.floor(Math.random()*0xFFFFFFFF) })

Either way, you should initialize a random seed only once. After that, whenever
you use a seed, you'll get another one back.
-}
initialSeed : Int -> Seed
initialSeed x =
    let
        (Seed state1 incr) =
            next (Seed 0 1013904223)

        state2 =
            state1 + x
    in
        next (Seed state2 incr)



{--
The magic constants 1013904223 and 1664525 are from Numerical Recipes. They are
inlined for performance.
--}

<commit_msg>Ensure initial seed is in range<commit_after>module Random.Pcg exposing (Generator, Seed, bool, int, float, oneIn, sample, pair, list, maybe, choice, choices, frequency, map, map2, map3, map4, map5, andMap, filter, constant, andThen, minInt, maxInt, step, generate, initialSeed, independentSeed, fastForward, toJson, fromJson)

{-| Generate psuedo-random numbers and values, by constructing
[generators](#Generator) for them. There are a bunch of basic generators like
[`bool`](#bool) and [`int`](#int) that you can build up into fancier generators
with functions like [`list`](#list) and [`map`](#map).

You run a `Generator` by calling the [`step`](#step) function, which
also takes a random [`Seed`](#Seed), and passes back a new seed. You should
never use the same seed twice because you will get the same result! If you need
random values over time, you should store the most recent seed in your model.
Alternatively, use [`generate`](#generate) to obtain random values from the Elm
runtime.

This is an implementation of [PCG](http://www.pcg-random.org/) by <NAME>,
and is not cryptographically secure.

# Getting Started
@docs initialSeed, step, generate

# Basic Generators
@docs Generator, bool, int, float, oneIn, sample

# Combining Generators
@docs pair, list, maybe, choice, choices, frequency

# Custom Generators
@docs constant, map, map2, map3, map4, map5, andMap, andThen, filter

# Working With Seeds
@docs Seed, independentSeed, fastForward, toJson, fromJson

# Constants
@docs minInt, maxInt
-}

import Bitwise
import Json.Encode
import Json.Decode
import Task
import Time


{-| A `Generator` is like a recipe for generating certain random values. So a
`Generator Int` describes how to generate integers and a `Generator String`
describes how to generate strings.
-}
type Generator a
    = Generator (Seed -> ( a, Seed ))


{-| Generate a random value as specified by a given `Generator`, using a `Seed`
and returning a new one.

In the following example, we are trying to generate numbers between 0 and 100
with the `int 0 100` generator. Each time we call `generate` we need to provide
a seed. This will produce a random number and a *new* seed to use if we want to
run other generators later.

    (x, seed1) = step (int 0 100) seed0
    (y, seed2) = step (int 0 100) seed1
    (z, seed3) = step (int 0 100) seed2
    [x, y, z] -- [85, 0, 38]

Notice that we use different seeds on each line. This is important! If you reuse
the same seed, you get the same results.

    (x, _) = step (int 0 100) seed0
    (y, _) = step (int 0 100) seed0
    (z, _) = step (int 0 100) seed0
    [x,y,z] -- [85, 85, 85]

As you can see, threading seeds through many calls to `step` is tedious and
error-prone. That's why this library includes many functions to build more
complicated generators, allowing you to call `step` only a small number of
times.

Our example is best written as:

    (xs, newSeed) = step (list 3 <| int 0 100) seed0
    xs -- [85, 0, 38]

-}
step : Generator a -> Seed -> ( a, Seed )
step (Generator generator) seed =
    generator seed


{-| Create a Command that will generate random values according to the supplied
`Generator`.

Think of this function as an alternative to `step`, since they both provide a
way to actually get the random values that you want. This function frees you
from worrying about seeds entirely, but as a tradeoff, you get your random
values asynchronously, in their own Message. Additionally, due to constraints on
third-party packages, it's possible that multiple commands sent at the same
moment will return the same values.

You can also think of this function as an alternative to `independentSeed`,
since they both allow you to use randomness in deeply nested components. In the
case of this function, it's through sending Commands up the chain that you have
to set up anyway.
-}
generate : (a -> msg) -> Generator a -> Cmd msg
generate toMsg generator =
    Time.now
        |> Task.map (round >> initialSeed >> step generator >> fst)
        |> Task.perform never toMsg


never : Never -> a
never a =
    never a


{-| A `Seed` is the source of randomness in the whole system. It hides the
current state of the random number generator.

Generators, not seeds, are the primary data structure for generating random
values. Generators are much easier to chain and combine than functions that take
and return seeds. Creating and managing seeds should happen "high up" in your
program.
-}
type Seed
    = Seed Int Int


{-| Initialize the state of the random number generator. The input should be
a randomly chosen 32-bit integer. You can generate and copy random integers to
create a reproducible psuedo-random generator.

    $ node
    > Math.floor(Math.random()*0xFFFFFFFF)
    227852860

    -- Elm
    seed0 : Seed
    seed0 = initialSeed 227852860

Alternatively, you can generate the random integers on page load and pass them
through a port. The program will be different every time.

    -- Elm
    port randomSeed : Int

    seed0 : Seed
    seed0 = initialSeed randomSeed

    -- JS
    Elm.ModuleName.fullscreen(
      { randomSeed: Math.floor(Math.random()*0xFFFFFFFF) })

Either way, you should initialize a random seed only once. After that, whenever
you use a seed, you'll get another one back.
-}
initialSeed : Int -> Seed
initialSeed x =
    let
        (Seed state1 incr) =
            next (Seed 0 1013904223)

        state2 =
            Bitwise.shiftRightLogical (state1 + x) 0
    in
        next (Seed state2 incr)



{--
The magic constants 1013904223 and 1664525 are from Numerical Recipes. They are
inlined for performance.
--}


{'fraction_non_alphanumeric': 0.08050393137955683, 'fraction_numerical': 0.023141529664045746, 'mean_word_length': 3.634782608695652, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '188563', 'n_tokens_mistral': 3470, 'n_tokens_neox': 3154, 'n_words': 1609}