SHARE
TWEET

Untitled

a guest Aug 20th, 2019 69 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. namespace Minotaur.Random {
  2.     using System;
  3.     using System.Buffers;
  4.     using System.Collections.Generic;
  5.     using System.Runtime.InteropServices;
  6.     using Minotaur.Collections;
  7.     using Minotaur.ExtensionMethods.Float;
  8.  
  9.     public static class ThreadStaticRandom {
  10.         // ThreadStatic to make sure that each thread gets a Random for itself, preventing the corruption
  11.         // of the Random object
  12.         [ThreadStatic]
  13.         private static Random _instance;
  14.  
  15.         // This wraps the _random variable to make sure each thread gets a Random for itself
  16.         private static Random Instance {
  17.             get {
  18.                 if (_instance == null)
  19.                     _instance = new Random();
  20.  
  21.                 return _instance;
  22.             }
  23.         }
  24.  
  25.         public static bool Bool() {
  26.             return Instance.NextDouble() < 0.5;
  27.         }
  28.  
  29.         public static bool Bool(float biasForTrue) {
  30.             if (float.IsNaN(biasForTrue))
  31.                 throw new ArgumentOutOfRangeException(nameof(biasForTrue) + " can't be NaN");
  32.             if (biasForTrue < 0 || biasForTrue > 1)
  33.                 throw new ArgumentOutOfRangeException(nameof(biasForTrue) + " must be in [0, 1] interval");
  34.  
  35.             return Uniform() < biasForTrue;
  36.         }
  37.  
  38.         public static double Uniform() {
  39.             return Instance.NextDouble();
  40.         }
  41.  
  42.         public static double Uniform(float inclusiveMin, float exclusiveMax) {
  43.             if (inclusiveMin.IsNanOrInfinity())
  44.                 throw new ArgumentOutOfRangeException(nameof(inclusiveMin) + " can't be NaN nor Infinity");
  45.             if (exclusiveMax.IsNanOrInfinity())
  46.                 throw new ArgumentOutOfRangeException(nameof(exclusiveMax) + " can't be NaN nor Infinity");
  47.             if (inclusiveMin > exclusiveMax)
  48.                 throw new ArgumentException(nameof(inclusiveMin) + " must be <= " + nameof(exclusiveMax));
  49.  
  50.             double range = exclusiveMax - inclusiveMin;
  51.             range *= Uniform();
  52.  
  53.             return inclusiveMin + range;
  54.         }
  55.  
  56.         public static int Int(int exclusiveMax) {
  57.             return Instance.Next(minValue: 0, maxValue: exclusiveMax);
  58.         }
  59.  
  60.         public static int Int(int inclusiveMin, int exclusiveMax) {
  61.             return Instance.Next(minValue: inclusiveMin, maxValue: exclusiveMax);
  62.         }
  63.  
  64.         public static bool[] RandomLabels(int count) {
  65.             if (count < 0)
  66.                 throw new ArgumentOutOfRangeException(nameof(count) + " must be > 0");
  67.  
  68.             var labels = new bool[count];
  69.             // Todo: if shit hits the fan (it shouldn't), check this out
  70.             var bytes = MemoryMarshal.AsBytes<bool>(labels);
  71.             Instance.NextBytes(bytes);
  72.             for (int i = 0; i < bytes.Length; i++)
  73.                 bytes[i] >>= 7;
  74.  
  75.             return labels;
  76.         }
  77.  
  78.         public static T Choice<T>(T first, T second) {
  79.             if (Bool())
  80.                 return first;
  81.             else
  82.                 return second;
  83.         }
  84.  
  85.         public static T Choice<T>(IReadOnlyList<T> values) {
  86.             if (values == null)
  87.                 throw new ArgumentNullException(nameof(values));
  88.             if (values.Count == 0)
  89.                 throw new ArgumentException(nameof(values) + " can't be empty");
  90.  
  91.             var index = Instance.Next(minValue: 0, maxValue: values.Count);
  92.             return values[index];
  93.         }
  94.  
  95.         public static T Choice<T>(Array<T> values) {
  96.             if (values == null)
  97.                 throw new ArgumentNullException(nameof(values));
  98.             if (values.Length == 0)
  99.                 throw new ArgumentException(nameof(values) + " can't be empty");
  100.  
  101.             var index = Instance.Next(minValue: 0, maxValue: values.Length);
  102.             return values[index];
  103.         }
  104.  
  105.         public static T Choice<T>(ReadOnlySpan<T> values) {
  106.             if (values.Length == 0)
  107.                 throw new ArgumentException(nameof(values) + " can't be empty");
  108.  
  109.             var index = Instance.Next(minValue: 0, maxValue: values.Length);
  110.             return values[index];
  111.         }
  112.  
  113.         public static T Choice<T>(T[] values) {
  114.             if (values.Length == 0)
  115.                 throw new ArgumentException(nameof(values) + " can't be empty");
  116.  
  117.             var index = Instance.Next(minValue: 0, maxValue: values.Length);
  118.             return values[index];
  119.         }
  120.  
  121.         public static void Shuffle<T>(Span<T> values) {
  122.             if (values.Length == 0)
  123.                 throw new ArgumentException(nameof(values) + " can't be empty");
  124.  
  125.             var rng = Instance;
  126.             int n = values.Length;
  127.             while (n > 1) {
  128.                 n--;
  129.                 int k = rng.Next(n + 1);
  130.                 var temp = values[k];
  131.                 values[k] = values[n];
  132.                 values[n] = temp;
  133.             }
  134.         }
  135.  
  136.         public static void Shuffle<T>(T[] values) {
  137.             if (values == null)
  138.                 throw new ArgumentNullException(nameof(values));
  139.             if (values.Length == 0)
  140.                 throw new ArgumentException(nameof(values) + " can't be empty");
  141.  
  142.             var rng = Instance;
  143.             int n = values.Length;
  144.             while (n > 1) {
  145.                 n--;
  146.                 int k = rng.Next(n + 1);
  147.                 var temp = values[k];
  148.                 values[k] = values[n];
  149.                 values[n] = temp;
  150.             }
  151.         }
  152.  
  153.         public static void CopyRandomElements<T>(ReadOnlySpan<T> from, Span<T> to, int count) {
  154.             if (count < 0)
  155.                 throw new ArgumentOutOfRangeException(nameof(count) + " must be >= 0");
  156.             if (from.Length < count)
  157.                 throw new ArgumentException(nameof(from) + " must have at least 'count' elements");
  158.             if (to.Length < count)
  159.                 throw new ArgumentException(nameof(to) + "must have at least 'count' elements");
  160.  
  161.             var rentedBuffer = ArrayPool<int>.Shared.Rent(minimumLength: from.Length);
  162.             var indexes = rentedBuffer.AsSpan().Slice(
  163.                 start: 0,
  164.                 length: from.Length);
  165.  
  166.             for (int i = 0; i < indexes.Length; i++)
  167.                 indexes[i] = i;
  168.  
  169.             Shuffle(indexes);
  170.  
  171.             for (int i = 0; i < count; i++)
  172.                 to[i] = from[indexes[i]];
  173.  
  174.             ArrayPool<int>.Shared.Return(rentedBuffer);
  175.         }
  176.  
  177.         public static T[] SelectRandomElements<T>(ReadOnlySpan<T> from, int count) {
  178.             if (count < 0)
  179.                 throw new ArgumentOutOfRangeException(nameof(count) + " must be >= 0");
  180.  
  181.             var randomlySelected = new T[count];
  182.             CopyRandomElements(
  183.                 from: from,
  184.                 to: randomlySelected,
  185.                 count: count);
  186.  
  187.             return randomlySelected;
  188.         }
  189.     }
  190. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top