diff --git a/api_list.include.md b/api_list.include.md index f0be63f1..a1aacde8 100644 --- a/api_list.include.md +++ b/api_list.include.md @@ -638,10 +638,17 @@ #### Random + * `string GetHexString(int, bool)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.gethexstring?view=net-11.0#system-random-gethexstring(system-int32-system-boolean)) + * `void GetHexString(Span, bool)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.gethexstring?view=net-11.0#system-random-gethexstring(system-span((system-char))-system-boolean)) * `T[] GetItems(ReadOnlySpan, int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.getitems?view=net-11.0#system-random-getitems-1(system-readonlyspan((-0))-system-int32)) * `void GetItems(ReadOnlySpan, Span)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.getitems?view=net-11.0#system-random-getitems-1(system-readonlyspan((-0))-system-span((-0)))) * `T[] GetItems(T[], int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.getitems?view=net-11.0#system-random-getitems-1(-0()-system-int32)) + * `string GetString(ReadOnlySpan, int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.getstring?view=net-11.0) * `void NextBytes(Span)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.nextbytes?view=net-11.0#system-random-nextbytes(system-span((system-byte)))) + * `long NextInt64(long, long)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.nextint64?view=net-11.0#system-random-nextint64(system-int64-system-int64)) + * `long NextInt64(long)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.nextint64?view=net-11.0#system-random-nextint64(system-int64)) + * `long NextInt64()` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.nextint64?view=net-11.0#system-random-nextint64) + * `float NextSingle()` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.nextsingle?view=net-11.0) * `void Shuffle(Span)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.nextbytes?view=net-11.0#system-random-nextbytes(system-span((system-byte)))) * `void Shuffle(T[])` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.nextbytes?view=net-11.0#system-random-nextbytes(system-span((system-byte)))) * `Shared` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.random.shared?view=net-11.0) diff --git a/src/Consume/Consume.cs b/src/Consume/Consume.cs index aa2a1d39..ff17e730 100644 --- a/src/Consume/Consume.cs +++ b/src/Consume/Consume.cs @@ -960,6 +960,18 @@ void Random_Methods() var bufferArray = new byte[10]; random.Shuffle(bufferArray); + + var nextInt64 = random.NextInt64(); + nextInt64 = random.NextInt64(100); + nextInt64 = random.NextInt64(50, 100); + var nextSingle = random.NextSingle(); + var hexString = random.GetHexString(10); + hexString = random.GetHexString(10, lowercase: true); +#if FeatureMemory + Span hexDest = stackalloc char[10]; + random.GetHexString(hexDest); + var rndString = random.GetString("abc".AsSpan(), 10); +#endif } #if FeatureMemory diff --git a/src/Polyfill/Polyfill_Random.cs b/src/Polyfill/Polyfill_Random.cs index 5ec234e2..9068c4ab 100644 --- a/src/Polyfill/Polyfill_Random.cs +++ b/src/Polyfill/Polyfill_Random.cs @@ -78,6 +78,137 @@ public static T[] GetItems( #endif +#if !NET6_0_OR_GREATER + + /// + /// Returns a non-negative random integer. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.nextint64?view=net-11.0#system-random-nextint64 + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.nextint64?view=net-11.0#system-random-nextint64(system-int64) + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + + /// + /// Returns a random integer that is within a specified range. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.nextint64?view=net-11.0#system-random-nextint64(system-int64-system-int64) + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + + if (minValue == maxValue) + { + return minValue; + } + + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + + return (long)(result % range) + minValue; + } + + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.nextsingle?view=net-11.0 + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + +#endif + +#if !NET10_0_OR_GREATER + + /// + /// Creates a string filled with random hexadecimal characters. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.gethexstring?view=net-11.0#system-random-gethexstring(system-int32-system-boolean) + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + + if (stringLength == 0) + { + return string.Empty; + } + + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + + return new string(chars); + } + +#if FeatureMemory + + /// + /// Fills a buffer with random hexadecimal characters. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.gethexstring?view=net-11.0#system-random-gethexstring(system-span((system-char))-system-boolean) + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.getstring?view=net-11.0 + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + if (length == 0) + { + return string.Empty; + } + + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + + return new string(chars); + } + +#endif + +#endif + #if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && FeatureMemory /// diff --git a/src/Split/net461/Polyfill_Random.cs b/src/Split/net461/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/net461/Polyfill_Random.cs +++ b/src/Split/net461/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/net462/Polyfill_Random.cs b/src/Split/net462/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/net462/Polyfill_Random.cs +++ b/src/Split/net462/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/net47/Polyfill_Random.cs b/src/Split/net47/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/net47/Polyfill_Random.cs +++ b/src/Split/net47/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/net471/Polyfill_Random.cs b/src/Split/net471/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/net471/Polyfill_Random.cs +++ b/src/Split/net471/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/net472/Polyfill_Random.cs b/src/Split/net472/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/net472/Polyfill_Random.cs +++ b/src/Split/net472/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/net48/Polyfill_Random.cs b/src/Split/net48/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/net48/Polyfill_Random.cs +++ b/src/Split/net48/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/net481/Polyfill_Random.cs b/src/Split/net481/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/net481/Polyfill_Random.cs +++ b/src/Split/net481/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/net5.0/Polyfill_Random.cs b/src/Split/net5.0/Polyfill_Random.cs index 938c8901..cd7603bc 100644 --- a/src/Split/net5.0/Polyfill_Random.cs +++ b/src/Split/net5.0/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/net6.0/Polyfill_Random.cs b/src/Split/net6.0/Polyfill_Random.cs index 938c8901..962d5bed 100644 --- a/src/Split/net6.0/Polyfill_Random.cs +++ b/src/Split/net6.0/Polyfill_Random.cs @@ -61,6 +61,64 @@ public static T[] GetItems( } return result; } + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/net7.0/Polyfill_Random.cs b/src/Split/net7.0/Polyfill_Random.cs index 938c8901..962d5bed 100644 --- a/src/Split/net7.0/Polyfill_Random.cs +++ b/src/Split/net7.0/Polyfill_Random.cs @@ -61,6 +61,64 @@ public static T[] GetItems( } return result; } + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/net8.0/Polyfill_Random.cs b/src/Split/net8.0/Polyfill_Random.cs new file mode 100644 index 00000000..df85b379 --- /dev/null +++ b/src/Split/net8.0/Polyfill_Random.cs @@ -0,0 +1,65 @@ +// +#pragma warning disable +namespace Polyfills; +using System; +static partial class Polyfill +{ + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif +} diff --git a/src/Split/net9.0/Polyfill_Random.cs b/src/Split/net9.0/Polyfill_Random.cs new file mode 100644 index 00000000..df85b379 --- /dev/null +++ b/src/Split/net9.0/Polyfill_Random.cs @@ -0,0 +1,65 @@ +// +#pragma warning disable +namespace Polyfills; +using System; +static partial class Polyfill +{ + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif +} diff --git a/src/Split/netcoreapp2.0/Polyfill_Random.cs b/src/Split/netcoreapp2.0/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/netcoreapp2.0/Polyfill_Random.cs +++ b/src/Split/netcoreapp2.0/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/netcoreapp2.1/Polyfill_Random.cs b/src/Split/netcoreapp2.1/Polyfill_Random.cs index 938c8901..cd7603bc 100644 --- a/src/Split/netcoreapp2.1/Polyfill_Random.cs +++ b/src/Split/netcoreapp2.1/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/netcoreapp2.2/Polyfill_Random.cs b/src/Split/netcoreapp2.2/Polyfill_Random.cs index 938c8901..cd7603bc 100644 --- a/src/Split/netcoreapp2.2/Polyfill_Random.cs +++ b/src/Split/netcoreapp2.2/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/netcoreapp3.0/Polyfill_Random.cs b/src/Split/netcoreapp3.0/Polyfill_Random.cs index 938c8901..cd7603bc 100644 --- a/src/Split/netcoreapp3.0/Polyfill_Random.cs +++ b/src/Split/netcoreapp3.0/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/netcoreapp3.1/Polyfill_Random.cs b/src/Split/netcoreapp3.1/Polyfill_Random.cs index 938c8901..cd7603bc 100644 --- a/src/Split/netcoreapp3.1/Polyfill_Random.cs +++ b/src/Split/netcoreapp3.1/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/netstandard2.0/Polyfill_Random.cs b/src/Split/netstandard2.0/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/netstandard2.0/Polyfill_Random.cs +++ b/src/Split/netstandard2.0/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Split/netstandard2.1/Polyfill_Random.cs b/src/Split/netstandard2.1/Polyfill_Random.cs index 938c8901..cd7603bc 100644 --- a/src/Split/netstandard2.1/Polyfill_Random.cs +++ b/src/Split/netstandard2.1/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif /// /// Performs an in-place shuffle of an array. /// diff --git a/src/Split/uap10.0/Polyfill_Random.cs b/src/Split/uap10.0/Polyfill_Random.cs index 8b8a7843..9473a082 100644 --- a/src/Split/uap10.0/Polyfill_Random.cs +++ b/src/Split/uap10.0/Polyfill_Random.cs @@ -61,6 +61,103 @@ public static T[] GetItems( } return result; } + /// + /// Returns a non-negative random integer. + /// + public static long NextInt64(this Random target) => + target.NextInt64(long.MaxValue); + /// + /// Returns a non-negative random integer that is less than the specified maximum. + /// + public static long NextInt64(this Random target, long maxValue) => + target.NextInt64(0, maxValue); + /// + /// Returns a random integer that is within a specified range. + /// + public static long NextInt64(this Random target, long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(nameof(minValue)); + } + if (minValue == maxValue) + { + return minValue; + } + var range = (ulong)(maxValue - minValue); + var limit = ulong.MaxValue - ulong.MaxValue % range; + ulong result; + do + { + var buf = new byte[8]; + target.NextBytes(buf); + result = BitConverter.ToUInt64(buf, 0); + } while (result >= limit); + return (long)(result % range) + minValue; + } + /// + /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0. + /// + public static float NextSingle(this Random target) => + (float)target.NextDouble(); + /// + /// Creates a string filled with random hexadecimal characters. + /// + public static string GetHexString(this Random target, int stringLength, bool lowercase = false) + { + if (stringLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(stringLength)); + } + if (stringLength == 0) + { + return string.Empty; + } + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + var chars = new char[stringLength]; + for (var i = 0; i < stringLength; i++) + { + chars[i] = hexAlphabet[target.Next(16)]; + } + return new string(chars); + } +#if FeatureMemory + /// + /// Fills a buffer with random hexadecimal characters. + /// + public static void GetHexString(this Random target, Span destination, bool lowercase = false) + { + var hexAlphabet = lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + for (var i = 0; i < destination.Length; i++) + { + destination[i] = hexAlphabet[target.Next(16)]; + } + } + /// + /// Creates a string populated with characters chosen at random from the provided set of choices. + /// + public static string GetString(this Random target, ReadOnlySpan choices, int length) + { + if (choices.IsEmpty) + { + throw new ArgumentException("Choices cannot be empty.", nameof(choices)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + if (length == 0) + { + return string.Empty; + } + var chars = new char[length]; + for (var i = 0; i < length; i++) + { + chars[i] = choices[target.Next(choices.Length)]; + } + return new string(chars); + } +#endif #if FeatureMemory /// /// Fills the elements of a specified span of bytes with random numbers. diff --git a/src/Tests/PolyfillTests_Random.cs b/src/Tests/PolyfillTests_Random.cs index 2719dbc2..02ff8e8b 100644 --- a/src/Tests/PolyfillTests_Random.cs +++ b/src/Tests/PolyfillTests_Random.cs @@ -93,4 +93,88 @@ public async Task RandomShuffleArray() random.Shuffle(buffer); await Assert.That(buffer.ToArray().Any(b => b != 0)).IsTrue(); } + + [Test] + public async Task RandomNextInt64() + { + var random = new Random(); + var result = random.NextInt64(); + await Assert.That(result).IsGreaterThanOrEqualTo(0); + } + + [Test] + public async Task RandomNextInt64_MaxValue() + { + var random = new Random(); + var result = random.NextInt64(100); + await Assert.That(result).IsGreaterThanOrEqualTo(0); + await Assert.That(result).IsLessThan(100); + } + + [Test] + public async Task RandomNextInt64_MinMaxValue() + { + var random = new Random(); + var result = random.NextInt64(50, 100); + await Assert.That(result).IsGreaterThanOrEqualTo(50); + await Assert.That(result).IsLessThan(100); + } + + [Test] + public async Task RandomNextSingle() + { + var random = new Random(); + var result = random.NextSingle(); + await Assert.That(result).IsGreaterThanOrEqualTo(0.0f); + await Assert.That(result).IsLessThan(1.0f); + } + + [Test] + public async Task RandomGetHexString() + { + var random = new Random(); + var result = random.GetHexString(10); + await Assert.That(result.Length).IsEqualTo(10); + await Assert.That(result.All(c => "0123456789ABCDEF".Contains(c))).IsTrue(); + } + + [Test] + public async Task RandomGetHexString_Lowercase() + { + var random = new Random(); + var result = random.GetHexString(10, lowercase: true); + await Assert.That(result.Length).IsEqualTo(10); + await Assert.That(result.All(c => "0123456789abcdef".Contains(c))).IsTrue(); + } + +#if FeatureMemory + + [Test] + public Task RandomGetHexString_Span() + { + var random = new Random(); + Span destination = stackalloc char[10]; + random.GetHexString(destination); + var result = destination.ToString(); + if (result.Length != 10) + throw new($"Expected length 10 but got {result.Length}"); + if (!result.All(c => "0123456789ABCDEF".Contains(c))) + throw new("Expected only hex characters"); + return Task.CompletedTask; + } + + [Test] + public Task RandomGetString() + { + var random = new Random(); + ReadOnlySpan choices = "abc".AsSpan(); + var result = random.GetString(choices, 10); + if (result.Length != 10) + throw new($"Expected length 10 but got {result.Length}"); + if (!result.All(c => "abc".Contains(c))) + throw new("Expected only abc characters"); + return Task.CompletedTask; + } + +#endif }