Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider supporting CPython's random compatibility #201

Open
ignassew opened this issue Jun 4, 2023 · 1 comment
Open

Consider supporting CPython's random compatibility #201

ignassew opened this issue Jun 4, 2023 · 1 comment
Assignees
Labels
A-core Area: Core Mersenne Twister implementation. A-crate-features Area: Compile-time features or attributes. C-enhancement Category: New feature or request.

Comments

@ignassew
Copy link

ignassew commented Jun 4, 2023

In order to support CPython there are only a couple small changes required. I would like to suggest a MtPython struct that would generate values according to the CPython source code.

I am willing to write the code myself and submit a PR.

If you think that this doesn't suit your library, please consider at least adding this information to the README or the documentation.

Rust reference implementation:

use rand_mt::Mt;

const SEED: u32 = 2137;

fn main() {
    // Every python seed is converted, and initialized as a key: https://github.com/python/cpython/blob/ce558e69d4087dd3653207de78345fbb8a2c7835/Modules/_randommodule.c#LL355C8-L355C8
    let mut rng = Mt::new_with_key([SEED]);

    // CPython does this to get 64 bit float: https://github.com/python/cpython/blob/ce558e69d4087dd3653207de78345fbb8a2c7835/Modules/_randommodule.c#L181
    let a = rng.next_u32() >> 5;
    let b = rng.next_u32() >> 6;
    let n_rust = (a as f64 * 67108864.0 + b as f64) * (1.0 / 9007199254740992.0);

    // Python:
    // #!/bin/python3
    // import random
    //
    // SEED = 2137
    //
    // random.seed(SEED)
    // n_python = random.random()
    // assert n_python == 0.571786152497536
    let n_python = 0.571786152497536;

    assert_eq!(n_rust, n_python);
}

CPython random seed using bytearray: https://github.com/python/cpython/blob/ce558e69d4087dd3653207de78345fbb8a2c7835/Modules/_randommodule.c#LL355C8-L355C8
CPython random.random() implementation: https://github.com/python/cpython/blob/ce558e69d4087dd3653207de78345fbb8a2c7835/Modules/_randommodule.c#L181

Related to #192

@lopopolo lopopolo added A-core Area: Core Mersenne Twister implementation. C-enhancement Category: New feature or request. A-crate-features Area: Compile-time features or attributes. labels Jun 4, 2023
@lopopolo
Copy link
Member

lopopolo commented Jun 4, 2023

Thanks for doing the legwork to find the differences between CPython's and CRuby's RNGs @ignassew! This doesn't look like that much of a burden to support. I'd love to accept a contribution to make this happen.

Let's add the CPython support and gate it behind an optional cpython feature. Can you structure the source code so it looks like this:

$ tree src
src
├── lib.rs
├── mt
│   └── rand.rs
├── mt.rs
├── mt64
│   └── rand.rs
├── mt64.rs
├── python
│   ├── mt
│   │   └── rand.rs
│   └── mt.rs
├── python.rs
├── vectors
│   ├── mt.rs
│   └── mt64.rs
└── vectors.rs

7 directories, 10 files

Let's also add a tests/python_reproducability.rs test to match the Ruby one and capture your test case in the issue description.

There's some breaking changes I've been meaning to make (for example, I think I've revisited my stance on #31 since in practice everyone, myself included, prefers the Mt type alias in code) which means it should be no problem packaging this up to crates.io.

I do like your idea on adding documentation to the README about what other languages' RNGs this crate has reproducibility guarantees with.

I'll assign this ticket to you. Looking forward to a PR 🙇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-core Area: Core Mersenne Twister implementation. A-crate-features Area: Compile-time features or attributes. C-enhancement Category: New feature or request.
Development

No branches or pull requests

2 participants