Skip to content

Comments

Add Pcg64Dxsm: Double xor shift multiply#25

Open
nitz wants to merge 3 commits intoociaw:masterfrom
nitz:add-pcg64-dxsm
Open

Add Pcg64Dxsm: Double xor shift multiply#25
nitz wants to merge 3 commits intoociaw:masterfrom
nitz:add-pcg64-dxsm

Conversation

@nitz
Copy link

@nitz nitz commented Jul 10, 2023

This PR adds a single class, Pcg64Dxsm and associated tests/benchmarks.

The DXSM (double xor shift multiply) is a more modern PCG64 variant published by Melissa O'Neill. This variant is used in NumPy, and has as well been proposed for v2 of the random number generator in Golang's standard library. Additionally, it is available via the Rust crate rand_pcg.

The benefits of DXSM, as elaborated by Melissa:

This is a new, more powerful output permutation (added in 2019). It’s a more comprehensive scrambling than RXS M, but runs faster on 128-bit types. Although primarily intended for use at large sizes, also works at smaller sizes as well.

This permutation is similar to xorshift multiply hash functions, except that one of the multipliers is the LCG multiplier (to avoid needing to have a second constant) and the other is based on the low-order bits. This latter aspect means that the scrambling applied to the high bits depends on the low bits, and makes it (to my eye) impractical to back out the permutation without having the low-order bits.

Tony Finch wrote about DXSM and provided a minimal implementation as well, which served as inspiration for this PR.

Because the 64-bit variants of the PCG use 128-bit state variables, the code added in this PR is conditionally complied when the target defines NET7_0_OR_GREATER, so that it can make use of the .NET 7.0 System.UInt128 type.

Cheers, and let me know what you think!

nitz added 3 commits July 10, 2023 09:15
`UInt128` is only available in .NET 7 or later, so this function is conditionally compiled when the target is `NET7_0_OR_GREATER`.
The DXSM (double xor shift multiply) permutation function was added to the reference implementation of the PCG64 in 2019, with its creator Melissa O'Neill describing it:

> This is a new, more powerful output permutation (added in 2019). It’s a more comprehensive scrambling than RXS M, but runs faster on 128-bit types. Although primarily intended for use at large sizes, also works at smaller sizes as well.

A good summary and implementation are available via Tony Finch, [here](https://dotat.at/@/2023-06-21-pcg64-dxsm.html).
@ociaw
Copy link
Owner

ociaw commented Jul 15, 2023

Thank you for the PR! This algorithm looks like a good fit for RandN. However at the moment, I am uncertain how I want approach UInt128, given that it is not available for .NET 6 and below. I imagine having an RNG that is available only when targeting .NET 7 could cause confusion with consumers of RandN. I am also in the process of moving RNGs into their own projects and NuGet packages, outside of the main RandN project.
With that in mind, I think the Pcg64Dxsm RNG itself should be moved to its own subproject since that would allow it to target only .NET 7 (tests, benchmarks, NextUInt128ViaUInt64 can all stay where they are).

@nitz
Copy link
Author

nitz commented Jul 17, 2023

Oh that sounds great — I'll wait til I see you've pulled one out into it's own package and then rebase this to mimic that!

I 100% feel you on UInt128 too. I looked at what pre-7 packages were available that implemented a 128 bit integer, and didn't find any that looked solid enough to even discuss taking as a dependency.

I also spent a little bit seeing how painful it would be to conditionally add in "first class" support of the .NET 7 impl through the text templates and such, but it was such a major drag. Especially with UInt128 having no "C# Language" support, it doesn't get to behave like a normal type, which made it need custom implementations for much of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants