| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 | 
							- /* -*- Mode: js; js-indent-level: 2; -*- */
 
- /*
 
-  * Copyright 2011 Mozilla Foundation and contributors
 
-  * Licensed under the New BSD license. See LICENSE or:
 
-  * http://opensource.org/licenses/BSD-3-Clause
 
-  */
 
- // It turns out that some (most?) JavaScript engines don't self-host
 
- // `Array.prototype.sort`. This makes sense because C++ will likely remain
 
- // faster than JS when doing raw CPU-intensive sorting. However, when using a
 
- // custom comparator function, calling back and forth between the VM's C++ and
 
- // JIT'd JS is rather slow *and* loses JIT type information, resulting in
 
- // worse generated code for the comparator function than would be optimal. In
 
- // fact, when sorting with a comparator, these costs outweigh the benefits of
 
- // sorting in C++. By using our own JS-implemented Quick Sort (below), we get
 
- // a ~3500ms mean speed-up in `bench/bench.html`.
 
- function SortTemplate(comparator) {
 
- /**
 
-  * Swap the elements indexed by `x` and `y` in the array `ary`.
 
-  *
 
-  * @param {Array} ary
 
-  *        The array.
 
-  * @param {Number} x
 
-  *        The index of the first item.
 
-  * @param {Number} y
 
-  *        The index of the second item.
 
-  */
 
- function swap(ary, x, y) {
 
-   var temp = ary[x];
 
-   ary[x] = ary[y];
 
-   ary[y] = temp;
 
- }
 
- /**
 
-  * Returns a random integer within the range `low .. high` inclusive.
 
-  *
 
-  * @param {Number} low
 
-  *        The lower bound on the range.
 
-  * @param {Number} high
 
-  *        The upper bound on the range.
 
-  */
 
- function randomIntInRange(low, high) {
 
-   return Math.round(low + (Math.random() * (high - low)));
 
- }
 
- /**
 
-  * The Quick Sort algorithm.
 
-  *
 
-  * @param {Array} ary
 
-  *        An array to sort.
 
-  * @param {function} comparator
 
-  *        Function to use to compare two items.
 
-  * @param {Number} p
 
-  *        Start index of the array
 
-  * @param {Number} r
 
-  *        End index of the array
 
-  */
 
- function doQuickSort(ary, comparator, p, r) {
 
-   // If our lower bound is less than our upper bound, we (1) partition the
 
-   // array into two pieces and (2) recurse on each half. If it is not, this is
 
-   // the empty array and our base case.
 
-   if (p < r) {
 
-     // (1) Partitioning.
 
-     //
 
-     // The partitioning chooses a pivot between `p` and `r` and moves all
 
-     // elements that are less than or equal to the pivot to the before it, and
 
-     // all the elements that are greater than it after it. The effect is that
 
-     // once partition is done, the pivot is in the exact place it will be when
 
-     // the array is put in sorted order, and it will not need to be moved
 
-     // again. This runs in O(n) time.
 
-     // Always choose a random pivot so that an input array which is reverse
 
-     // sorted does not cause O(n^2) running time.
 
-     var pivotIndex = randomIntInRange(p, r);
 
-     var i = p - 1;
 
-     swap(ary, pivotIndex, r);
 
-     var pivot = ary[r];
 
-     // Immediately after `j` is incremented in this loop, the following hold
 
-     // true:
 
-     //
 
-     //   * Every element in `ary[p .. i]` is less than or equal to the pivot.
 
-     //
 
-     //   * Every element in `ary[i+1 .. j-1]` is greater than the pivot.
 
-     for (var j = p; j < r; j++) {
 
-       if (comparator(ary[j], pivot, false) <= 0) {
 
-         i += 1;
 
-         swap(ary, i, j);
 
-       }
 
-     }
 
-     swap(ary, i + 1, j);
 
-     var q = i + 1;
 
-     // (2) Recurse on each half.
 
-     doQuickSort(ary, comparator, p, q - 1);
 
-     doQuickSort(ary, comparator, q + 1, r);
 
-   }
 
- }
 
-   return doQuickSort;
 
- }
 
- function cloneSort(comparator) {
 
-   let template = SortTemplate.toString();
 
-   let templateFn = new Function(`return ${template}`)();
 
-   return templateFn(comparator);
 
- }
 
- /**
 
-  * Sort the given array in-place with the given comparator function.
 
-  *
 
-  * @param {Array} ary
 
-  *        An array to sort.
 
-  * @param {function} comparator
 
-  *        Function to use to compare two items.
 
-  */
 
- let sortCache = new WeakMap();
 
- exports.quickSort = function (ary, comparator, start = 0) {
 
-   let doQuickSort = sortCache.get(comparator);
 
-   if (doQuickSort === void 0) {
 
-     doQuickSort = cloneSort(comparator);
 
-     sortCache.set(comparator, doQuickSort);
 
-   }
 
-   doQuickSort(ary, comparator, start, ary.length - 1);
 
- };
 
 
  |