From a7194e1bc347a204661c939517067cf931c997b6 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 27 Nov 2020 15:41:35 +0900 Subject: [PATCH 1/5] add stateless RNG --- osu.Game/Utils/StatelessRNG.cs | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 osu.Game/Utils/StatelessRNG.cs diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs new file mode 100644 index 0000000000..8d08b26ca4 --- /dev/null +++ b/osu.Game/Utils/StatelessRNG.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Utils +{ + /// Provides a fast stateless function that can be used in randomly-looking visual elements. + public static class StatelessRNG + { + private static ulong mix(ulong x) + { + unchecked + { + x ^= x >> 33; + x *= 0xff51afd7ed558ccd; + x ^= x >> 33; + x *= 0xc4ceb9fe1a85ec53; + x ^= x >> 33; + return x; + } + } + + /// Compute an integer from given seed and series number. + /// + /// The seed value of this random number generator. + /// + /// + /// The series number. + /// Different values are computed for the same seed in different series. + /// + public static ulong Get(int seed, int series = 0) => + unchecked(mix(((ulong)(uint)series << 32) | ((uint)seed ^ 0x12345678))); + + /// Compute a floating point value between 0 and 1 (excluding 1) from given seed and series number. + /// + /// The seed value of this random number generator. + /// + /// + /// The series number. + /// Different values are computed for the same seed in different series. + /// + public static float GetSingle(int seed, int series = 0) => + (float)(Get(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision + } +} From 731e689f2da41dcaa040b5dde209f02b1306754d Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 18:07:37 +0900 Subject: [PATCH 2/5] Add summary tags to the doc comments --- osu.Game/Utils/StatelessRNG.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index 8d08b26ca4..d78d55cc09 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -3,7 +3,9 @@ namespace osu.Game.Utils { + /// /// Provides a fast stateless function that can be used in randomly-looking visual elements. + /// public static class StatelessRNG { private static ulong mix(ulong x) @@ -19,7 +21,9 @@ namespace osu.Game.Utils } } + /// /// Compute an integer from given seed and series number. + /// /// /// The seed value of this random number generator. /// @@ -30,7 +34,9 @@ namespace osu.Game.Utils public static ulong Get(int seed, int series = 0) => unchecked(mix(((ulong)(uint)series << 32) | ((uint)seed ^ 0x12345678))); + /// /// Compute a floating point value between 0 and 1 (excluding 1) from given seed and series number. + /// /// /// The seed value of this random number generator. /// From 51bddd4a0ff00fce883583852a2d225d5b41117c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 30 Nov 2020 18:46:28 +0900 Subject: [PATCH 3/5] Rename functions, and add NextInt. --- osu.Game/Utils/StatelessRNG.cs | 42 +++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index d78d55cc09..d316f718e3 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; + namespace osu.Game.Utils { /// @@ -22,7 +24,7 @@ namespace osu.Game.Utils } /// - /// Compute an integer from given seed and series number. + /// Generate a random 64-bit unsigned integer from given seed. /// /// /// The seed value of this random number generator. @@ -31,11 +33,39 @@ namespace osu.Game.Utils /// The series number. /// Different values are computed for the same seed in different series. /// - public static ulong Get(int seed, int series = 0) => - unchecked(mix(((ulong)(uint)series << 32) | ((uint)seed ^ 0x12345678))); + public static ulong NextUlong(int seed, int series = 0) + { + unchecked + { + // + var combined = ((ulong)(uint)series << 32) | (uint)seed; + // The xor operation is to not map (0, 0) to 0. + return mix(combined ^ 0x12345678); + } + } /// - /// Compute a floating point value between 0 and 1 (excluding 1) from given seed and series number. + /// Generate a random integer in range [0, maxValue) from given seed. + /// + /// + /// The number of possible results. + /// + /// + /// The seed value of this random number generator. + /// + /// + /// The series number. + /// Different values are computed for the same seed in different series. + /// + public static int NextInt(int maxValue, int seed, int series = 0) + { + if (maxValue <= 0) throw new ArgumentOutOfRangeException(nameof(maxValue)); + + return (int)(NextUlong(seed, series) % (ulong)maxValue); + } + + /// + /// Compute a random floating point value between 0 and 1 (excluding 1) from given seed and series number. /// /// /// The seed value of this random number generator. @@ -44,7 +74,7 @@ namespace osu.Game.Utils /// The series number. /// Different values are computed for the same seed in different series. /// - public static float GetSingle(int seed, int series = 0) => - (float)(Get(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision + public static float NextSingle(int seed, int series = 0) => + (float)(NextUlong(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision } } From 588a5c2aff768e7139d522b9e3acfe81d111afcf Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 1 Dec 2020 09:35:28 +0900 Subject: [PATCH 4/5] Remove empty comment --- osu.Game/Utils/StatelessRNG.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index d316f718e3..11d079498a 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -37,7 +37,6 @@ namespace osu.Game.Utils { unchecked { - // var combined = ((ulong)(uint)series << 32) | (uint)seed; // The xor operation is to not map (0, 0) to 0. return mix(combined ^ 0x12345678); From 2de3e655e07ad95dfdd9b25ee5d0a440567d7cb8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Dec 2020 12:59:45 +0900 Subject: [PATCH 5/5] Rename NextUlong -> NextULong --- osu.Game/Utils/StatelessRNG.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index 11d079498a..118b08fe30 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -33,7 +33,7 @@ namespace osu.Game.Utils /// The series number. /// Different values are computed for the same seed in different series. /// - public static ulong NextUlong(int seed, int series = 0) + public static ulong NextULong(int seed, int series = 0) { unchecked { @@ -60,7 +60,7 @@ namespace osu.Game.Utils { if (maxValue <= 0) throw new ArgumentOutOfRangeException(nameof(maxValue)); - return (int)(NextUlong(seed, series) % (ulong)maxValue); + return (int)(NextULong(seed, series) % (ulong)maxValue); } /// @@ -74,6 +74,6 @@ namespace osu.Game.Utils /// Different values are computed for the same seed in different series. /// public static float NextSingle(int seed, int series = 0) => - (float)(NextUlong(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision + (float)(NextULong(seed, series) & ((1 << 24) - 1)) / (1 << 24); // float has 24-bit precision } }