source: imaps-frontend/node_modules/source-map-js/lib/quick-sort.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 4.0 KB
RevLine 
[d565449]1/* -*- Mode: js; js-indent-level: 2; -*- */
2/*
3 * Copyright 2011 Mozilla Foundation and contributors
4 * Licensed under the New BSD license. See LICENSE or:
5 * http://opensource.org/licenses/BSD-3-Clause
6 */
7
8// It turns out that some (most?) JavaScript engines don't self-host
9// `Array.prototype.sort`. This makes sense because C++ will likely remain
10// faster than JS when doing raw CPU-intensive sorting. However, when using a
11// custom comparator function, calling back and forth between the VM's C++ and
12// JIT'd JS is rather slow *and* loses JIT type information, resulting in
13// worse generated code for the comparator function than would be optimal. In
14// fact, when sorting with a comparator, these costs outweigh the benefits of
15// sorting in C++. By using our own JS-implemented Quick Sort (below), we get
16// a ~3500ms mean speed-up in `bench/bench.html`.
17
18function SortTemplate(comparator) {
19
20/**
21 * Swap the elements indexed by `x` and `y` in the array `ary`.
22 *
23 * @param {Array} ary
24 * The array.
25 * @param {Number} x
26 * The index of the first item.
27 * @param {Number} y
28 * The index of the second item.
29 */
30function swap(ary, x, y) {
31 var temp = ary[x];
32 ary[x] = ary[y];
33 ary[y] = temp;
34}
35
36/**
37 * Returns a random integer within the range `low .. high` inclusive.
38 *
39 * @param {Number} low
40 * The lower bound on the range.
41 * @param {Number} high
42 * The upper bound on the range.
43 */
44function randomIntInRange(low, high) {
45 return Math.round(low + (Math.random() * (high - low)));
46}
47
48/**
49 * The Quick Sort algorithm.
50 *
51 * @param {Array} ary
52 * An array to sort.
53 * @param {function} comparator
54 * Function to use to compare two items.
55 * @param {Number} p
56 * Start index of the array
57 * @param {Number} r
58 * End index of the array
59 */
60function doQuickSort(ary, comparator, p, r) {
61 // If our lower bound is less than our upper bound, we (1) partition the
62 // array into two pieces and (2) recurse on each half. If it is not, this is
63 // the empty array and our base case.
64
65 if (p < r) {
66 // (1) Partitioning.
67 //
68 // The partitioning chooses a pivot between `p` and `r` and moves all
69 // elements that are less than or equal to the pivot to the before it, and
70 // all the elements that are greater than it after it. The effect is that
71 // once partition is done, the pivot is in the exact place it will be when
72 // the array is put in sorted order, and it will not need to be moved
73 // again. This runs in O(n) time.
74
75 // Always choose a random pivot so that an input array which is reverse
76 // sorted does not cause O(n^2) running time.
77 var pivotIndex = randomIntInRange(p, r);
78 var i = p - 1;
79
80 swap(ary, pivotIndex, r);
81 var pivot = ary[r];
82
83 // Immediately after `j` is incremented in this loop, the following hold
84 // true:
85 //
86 // * Every element in `ary[p .. i]` is less than or equal to the pivot.
87 //
88 // * Every element in `ary[i+1 .. j-1]` is greater than the pivot.
89 for (var j = p; j < r; j++) {
90 if (comparator(ary[j], pivot, false) <= 0) {
91 i += 1;
92 swap(ary, i, j);
93 }
94 }
95
96 swap(ary, i + 1, j);
97 var q = i + 1;
98
99 // (2) Recurse on each half.
100
101 doQuickSort(ary, comparator, p, q - 1);
102 doQuickSort(ary, comparator, q + 1, r);
103 }
104}
105
106 return doQuickSort;
107}
108
109function cloneSort(comparator) {
110 let template = SortTemplate.toString();
111 let templateFn = new Function(`return ${template}`)();
112 return templateFn(comparator);
113}
114
115/**
116 * Sort the given array in-place with the given comparator function.
117 *
118 * @param {Array} ary
119 * An array to sort.
120 * @param {function} comparator
121 * Function to use to compare two items.
122 */
123
124let sortCache = new WeakMap();
125exports.quickSort = function (ary, comparator, start = 0) {
126 let doQuickSort = sortCache.get(comparator);
127 if (doQuickSort === void 0) {
128 doQuickSort = cloneSort(comparator);
129 sortCache.set(comparator, doQuickSort);
130 }
131 doQuickSort(ary, comparator, start, ary.length - 1);
132};
Note: See TracBrowser for help on using the repository browser.