text: /*!
   * @author electricessence / https://github.com/electricessence/
   * Licensing: MIT
   */
  import { Integer } from "./Integer";
  import { initialize } from "./Collections/Array/initialize";
  import { shuffle as arrayShuffle } from "./Collections/Array/shuffle";
  var assert = Integer.assert;
  /**
   * This module only acts as a utility API for getting random numbers from Math.random().
   * If you need repeatable seeded random numbers then you'll need a separate utility.
   * Highly recommended: https://github.com/ckknight/random-js which has typings under @types/random-js.
   */
  export var Random;
  (function (Random) {
      function r(maxExclusive = 1) {
          return Math.floor(Math.random() * maxExclusive);
      }
      function nr(boundary, inclusive) {
          const a = Math.abs(boundary);
          if (a === 0 || a === 1 && !inclusive)
              return 0;
          if (inclusive)
              boundary += boundary / a;
          return r(boundary);
      }
      function arrayCopy(source) {
          const len = source.length;
          const result = initialize(len);
          for (let i = 0; i < len; i++) {
              result[i] = source[i];
          }
          return result;
      }
      /**
       * Returns a random integer from 0 to the maxExclusive.
       * Negative numbers are allowed.
       *
       * @param maxExclusive
       * @returns {number}
       */
      function integer(maxExclusive) {
          return next(maxExclusive);
      }
      Random.integer = integer;
      /**
       * Returns a function that generates random floating point numbers up to the maxExclusive value.
       * Useful for generating a random and memoizable set for use with other enumerables.
       * @param maxExclusive
       * @returns {()=>number}
       */
      function generate(maxExclusive = 1) {
          return () => r(maxExclusive);
      }
      Random.generate = generate;
      (function (generate) {
          /**
           * Returns a function that generates random integers up to the boundary.
           * Useful for generating a random and memoizable set for use with other enumerables.
           * @param boundary
           * @param inclusive
           * @returns {()=>number}
           */
          function integers(boundary, inclusive) {
              return () => nr(boundary, inclusive);
          }
          generate.integers = integers;
      })(generate = Random.generate || (Random.generate = {}));
      /**
       * Returns a random integer from 0 to the boundary.
       * Return value will be less than the boundary unless inclusive is set to true.
       * Negative numbers are allowed.
       *
       * @param boundary
       * @param inclusive
       * @returns {number}
       */
      function next(boundary, inclusive) {
          assert(boundary, 'boundary');
          return nr(boundary, inclusive);
      }
      Random.next = next;
      (function (next) {
          function integer(boundary, inclusive) {
              return Random.next(boundary, inclusive);
          }
          next.integer = integer;
          function float(boundary = Number.MAX_VALUE) {
              if (isNaN(boundary))
                  throw "'boundary' is not a number.";
              return Math.random() * boundary;
          }
          next.float = float;
          function inRange(min, max, inclusive) {
              assert(min, 'min');
              assert(max, 'max');
              let range = max - min;
              if (range === 0)
                  return min;
              if (inclusive)
                  range += range / Math.abs(range);
              return min + r(range);
          }
          next.inRange = inRange;
      })(next = Random.next || (Random.next = {}));
      /**
       * Returns an array of random integers.
       * @param count
       * @param boundary
       * @param inclusive
       * @returns {number[]}
       */
      function integers(count, boundary, inclusive) {
          assert(count);
          const s = [];
          s.length = count;
          for (let i = 0; i < count; i++) {
              s[i] = nr(boundary, inclusive);
          }
          return s;
      }
      Random.integers = integers;
      /**
       * Shuffles an array.
       * @param target
       * @returns {T}
       */
      function shuffle(target) {
          return arrayShuffle(target);
      }
      Random.shuffle = shuffle;
      /**
       * Creates a copy of an array-like  and returns it shuffled.
       * @param source
       * @returns {T[]}
       */
      function copy(source) {
          return arrayShuffle(arrayCopy(source));
      }
      Random.copy = copy;
      /**
       * Returns a distinct random set from the source array up to the maxCount or the full length of the array.
       * @param source
       * @param maxCount
       * @returns {any}
       */
      function select(source, maxCount) {
          if (maxCount !== Infinity)
              Integer.assertZeroOrGreater(maxCount);
          switch (maxCount) {
              case 0:
                  return [];
              case 1:
                  return [select.one(source, true)];
              default:
                  let result = arrayShuffle(arrayCopy(source));
                  if (maxCount < result.length)
                      result.length = maxCount;
                  return result;
          }
      }
      Random.select = select;
      (function (select) {
          function one(source, throwIfEmpty) {
              if (source && source.length)
                  return source[r(source.length)];
              if (throwIfEmpty)
                  throw "Cannot select from an empty set.";
          }
          select.one = one;
      })(select = Random.select || (Random.select = {}));
  })(Random || (Random = {}));
  //# sourceMappingURL=Random.js.map