progress on migrating to heex templates and font-icons

This commit is contained in:
Adam Piontek 2022-08-13 07:32:36 -04:00
parent d43daafdb7
commit 3eff955672
21793 changed files with 2161968 additions and 16895 deletions

48
assets_old/node_modules/timsort/.npmignore generated vendored Normal file
View file

@ -0,0 +1,48 @@
# Development stuff
test/
Gruntfile.js
# Configuration files
.jscsrc
.jshintrc
.eslintrc
.travis.yml
bower.json
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# Deployed apps should consider commenting this line out:
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules
# JetBrains exclusion
.idea
# Source files
# src
# example files
examples
# Benchmark files
benchmark

21
assets_old/node_modules/timsort/LICENSE.md generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2015 Marco Ziccardi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

264
assets_old/node_modules/timsort/README.md generated vendored Normal file
View file

@ -0,0 +1,264 @@
# Node-TimSort: Fast Sorting for Node.js
[![Build Status](https://travis-ci.org/mziccard/node-timsort.svg?branch=master)](https://travis-ci.org/mziccard/node-timsort)
[![npm version](https://badge.fury.io/js/timsort.svg)](https://www.npmjs.com/package/timsort)
An adaptive and **stable** sort algorithm based on merging that requires fewer than nlog(n)
comparisons when run on partially sorted arrays. The algorithm uses O(n) memory and still runs in O(nlogn)
(worst case) on random arrays.
This implementation is based on the original
[TimSort](http://svn.python.org/projects/python/trunk/Objects/listsort.txt) developed
by Tim Peters for Python's lists (code [here](http://svn.python.org/projects/python/trunk/Objects/listobject.c)).
TimSort has been also adopted in Java starting from version 7.
## Acknowledgments
- @novacrazy: ported the module to ES6/ES7 and made it available via bower
- @kasperisager: implemented faster lexicographic comparison of small integers
## Usage
Install the package with npm:
```
npm install --save timsort
```
And use it:
```javascript
var TimSort = require('timsort');
var arr = [...];
TimSort.sort(arr);
```
You can also install it with bower:
```
bower install timsort
```
As `array.sort()` by default the `timsort` module sorts according to
lexicographical order.
You can also provide your own compare function (to sort any object) as:
```javascript
function numberCompare(a,b) {
return a-b;
}
var arr = [...];
var TimSort = require('timsort');
TimSort.sort(arr, numberCompare);
```
You can also sort only a specific subrange of the array:
```javascript
TimSort.sort(arr, 5, 10);
TimSort.sort(arr, numberCompare, 5, 10);
```
## Performance
A benchmark is provided in `benchmark/index.js`. It compares the `timsort` module against
the default `array.sort` method in the numerical sorting of different types of integer array
(as described [here](http://svn.python.org/projects/python/trunk/Objects/listsort.txt)):
- *Random array*
- *Descending array*
- *Ascending array*
- *Ascending array with 3 random exchanges*
- *Ascending array with 10 random numbers in the end*
- *Array of equal elements*
- *Random Array with many duplicates*
- *Random Array with some duplicates*
For any of the array types the sorting is repeated several times and for
different array sizes, average execution time is then printed.
I run the benchmark on Node v6.3.1 (both pre-compiled and compiled from source,
results are very similar), obtaining the following values:
<table>
<tr>
<th></th><th></th>
<th colspan="2">Execution Time (ns)</th>
<th rowspan="2">Speedup</th>
</tr>
<tr>
<th>Array Type</th>
<th>Length</th>
<th>TimSort.sort</th>
<th>array.sort</th>
</tr>
<tbody>
<tr>
<td rowspan="4">Random</td><td>10</td><td>404</td><td>1583</td><td>3.91</td>
</tr>
<tr>
<td>100</td><td>7147</td><td>4442</td><td>0.62</td>
</tr>
<tr>
<td>1000</td><td>96395</td><td>59979</td><td>0.62</td>
</tr>
<tr>
<td>10000</td><td>1341044</td><td>6098065</td><td>4.55</td>
</tr>
<tr>
<td rowspan="4">Descending</td><td>10</td><td>180</td><td>1881</td><td>10.41</td>
</tr>
<tr>
<td>100</td><td>682</td><td>19210</td><td>28.14</td>
</tr>
<tr>
<td>1000</td><td>3809</td><td>185185</td><td>48.61</td>
</tr>
<tr>
<td>10000</td><td>35878</td><td>5392428</td><td>150.30</td>
</tr>
<tr>
<td rowspan="4">Ascending</td><td>10</td><td>173</td><td>816</td><td>4.69</td>
</tr>
<tr>
<td>100</td><td>578</td><td>18147</td><td>31.34</td>
</tr>
<tr>
<td>1000</td><td>2551</td><td>331993</td><td>130.12</td>
</tr>
<tr>
<td>10000</td><td>22098</td><td>5382446</td><td>243.57</td>
</tr>
<tr>
<td rowspan="4">Ascending + 3 Rand Exc</td><td>10</td><td>232</td><td>927</td><td>3.99</td>
</tr>
<tr>
<td>100</td><td>1059</td><td>15792</td><td>14.90</td>
</tr>
<tr>
<td>1000</td><td>3525</td><td>300708</td><td>85.29</td>
</tr>
<tr>
<td>10000</td><td>27455</td><td>4781370</td><td>174.15</td>
</tr>
<tr>
<td rowspan="4">Ascending + 10 Rand End</td><td>10</td><td>378</td><td>1425</td><td>3.77</td>
</tr>
<tr>
<td>100</td><td>1707</td><td>23346</td><td>13.67</td>
</tr>
<tr>
<td>1000</td><td>5818</td><td>334744</td><td>57.53</td>
</tr>
<tr>
<td>10000</td><td>38034</td><td>4985473</td><td>131.08</td>
</tr>
<tr>
<td rowspan="4">Equal Elements</td><td>10</td><td>164</td><td>766</td><td>4.68</td>
</tr>
<tr>
<td>100</td><td>520</td><td>3188</td><td>6.12</td>
</tr>
<tr>
<td>1000</td><td>2340</td><td>27971</td><td>11.95</td>
</tr>
<tr>
<td>10000</td><td>17011</td><td>281672</td><td>16.56</td>
</tr>
<tr>
<td rowspan="4">Many Repetitions</td><td>10</td><td>396</td><td>1482</td><td>3.74</td>
</tr>
<tr>
<td>100</td><td>7282</td><td>25267</td><td>3.47</td>
</tr>
<tr>
<td>1000</td><td>105528</td><td>420120</td><td>3.98</td>
</tr>
<tr>
<td>10000</td><td>1396120</td><td>5787399</td><td>4.15</td>
</tr>
<tr>
<td rowspan="4">Some Repetitions</td><td>10</td><td>390</td><td>1463</td><td>3.75</td>
</tr>
<tr>
<td>100</td><td>6678</td><td>20082</td><td>3.01</td>
</tr>
<tr>
<td>1000</td><td>104344</td><td>374103</td><td>3.59</td>
</tr>
<tr>
<td>10000</td><td>1333816</td><td>5474000</td><td>4.10</td>
</tr>
</tbody>
</table>
`TimSort.sort` **is faster** than `array.sort` on almost of the tested array types.
In general, the more ordered the array is the better `TimSort.sort` performs with respect to `array.sort` (up to 243 times faster on already sorted arrays).
And also, in general, the bigger the array the more we benefit from using
the `timsort` module.
These data strongly depend on Node.js version and the machine on which the benchmark is run. I strongly encourage you to run the benchmark on your own setup with:
```
npm run benchmark
```
Please also notice that:
- This benchmark is far from exhaustive. Several cases are not considered
and the results must be taken as partial
- *inlining* is surely playing an active role in `timsort` module's good performance
- A more accurate comparison of the algorithms would require implementing `array.sort` in pure javascript
and counting element comparisons
## Stability
TimSort is *stable* which means that equal items maintain their relative order
after sorting. Stability is a desirable property for a sorting algorithm.
Consider the following array of items with an height and a weight.
```javascript
[
{ height: 100, weight: 80 },
{ height: 90, weight: 90 },
{ height: 70, weight: 95 },
{ height: 100, weight: 100 },
{ height: 80, weight: 110 },
{ height: 110, weight: 115 },
{ height: 100, weight: 120 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 100, weight: 135 },
{ height: 75, weight: 140 },
{ height: 70, weight: 140 }
]
```
Items are already sorted by `weight`. Sorting the array
according to the item's `height` with the `timsort` module
results in the following array:
```javascript
[
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 70, weight: 140 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 80 },
{ height: 100, weight: 100 },
{ height: 100, weight: 120 },
{ height: 100, weight: 135 },
{ height: 110, weight: 115 }
]
```
Items with the same `height` are still sorted by `weight` which means they preserved their relative order.
`array.sort`, instead, is not guarranteed to be *stable*. In Node v0.12.7
sorting the previous array by `height` with `array.sort` results in:
```javascript
[
{ height: 70, weight: 140 },
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 100 },
{ height: 100, weight: 80 },
{ height: 100, weight: 135 },
{ height: 100, weight: 120 },
{ height: 110, weight: 115 }
]
```
As you can see the sorting did not preserve `weight` ordering for items with the
same `height`.

815
assets_old/node_modules/timsort/build/timsort.js generated vendored Normal file
View file

@ -0,0 +1,815 @@
/****
* The MIT License
*
* Copyright (c) 2015 Marco Ziccardi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
****/
(function (global, factory) {
if (typeof define === 'function' && define.amd) {
define('timsort', ['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
var mod = {
exports: {}
};
factory(mod.exports);
global.timsort = mod.exports;
}
})(this, function (exports) {
'use strict';
exports.__esModule = true;
exports.sort = sort;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function');
}
}
var DEFAULT_MIN_MERGE = 32;
var DEFAULT_MIN_GALLOPING = 7;
var DEFAULT_TMP_STORAGE_LENGTH = 256;
var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9];
function log10(x) {
if (x < 1e5) {
if (x < 1e2) {
return x < 1e1 ? 0 : 1;
}
if (x < 1e4) {
return x < 1e3 ? 2 : 3;
}
return 4;
}
if (x < 1e7) {
return x < 1e6 ? 5 : 6;
}
if (x < 1e9) {
return x < 1e8 ? 7 : 8;
}
return 9;
}
function alphabeticalCompare(a, b) {
if (a === b) {
return 0;
}
if (~ ~a === a && ~ ~b === b) {
if (a === 0 || b === 0) {
return a < b ? -1 : 1;
}
if (a < 0 || b < 0) {
if (b >= 0) {
return -1;
}
if (a >= 0) {
return 1;
}
a = -a;
b = -b;
}
var al = log10(a);
var bl = log10(b);
var t = 0;
if (al < bl) {
a *= POWERS_OF_TEN[bl - al - 1];
b /= 10;
t = -1;
} else if (al > bl) {
b *= POWERS_OF_TEN[al - bl - 1];
a /= 10;
t = 1;
}
if (a === b) {
return t;
}
return a < b ? -1 : 1;
}
var aStr = String(a);
var bStr = String(b);
if (aStr === bStr) {
return 0;
}
return aStr < bStr ? -1 : 1;
}
function minRunLength(n) {
var r = 0;
while (n >= DEFAULT_MIN_MERGE) {
r |= n & 1;
n >>= 1;
}
return n + r;
}
function makeAscendingRun(array, lo, hi, compare) {
var runHi = lo + 1;
if (runHi === hi) {
return 1;
}
if (compare(array[runHi++], array[lo]) < 0) {
while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
runHi++;
}
reverseRun(array, lo, runHi);
} else {
while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
runHi++;
}
}
return runHi - lo;
}
function reverseRun(array, lo, hi) {
hi--;
while (lo < hi) {
var t = array[lo];
array[lo++] = array[hi];
array[hi--] = t;
}
}
function binaryInsertionSort(array, lo, hi, start, compare) {
if (start === lo) {
start++;
}
for (; start < hi; start++) {
var pivot = array[start];
var left = lo;
var right = start;
while (left < right) {
var mid = left + right >>> 1;
if (compare(pivot, array[mid]) < 0) {
right = mid;
} else {
left = mid + 1;
}
}
var n = start - left;
switch (n) {
case 3:
array[left + 3] = array[left + 2];
case 2:
array[left + 2] = array[left + 1];
case 1:
array[left + 1] = array[left];
break;
default:
while (n > 0) {
array[left + n] = array[left + n - 1];
n--;
}
}
array[left] = pivot;
}
}
function gallopLeft(value, array, start, length, hint, compare) {
var lastOffset = 0;
var maxOffset = 0;
var offset = 1;
if (compare(value, array[start + hint]) > 0) {
maxOffset = length - hint;
while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
lastOffset += hint;
offset += hint;
} else {
maxOffset = hint + 1;
while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
var tmp = lastOffset;
lastOffset = hint - offset;
offset = hint - tmp;
}
lastOffset++;
while (lastOffset < offset) {
var m = lastOffset + (offset - lastOffset >>> 1);
if (compare(value, array[start + m]) > 0) {
lastOffset = m + 1;
} else {
offset = m;
}
}
return offset;
}
function gallopRight(value, array, start, length, hint, compare) {
var lastOffset = 0;
var maxOffset = 0;
var offset = 1;
if (compare(value, array[start + hint]) < 0) {
maxOffset = hint + 1;
while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
var tmp = lastOffset;
lastOffset = hint - offset;
offset = hint - tmp;
} else {
maxOffset = length - hint;
while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
lastOffset += hint;
offset += hint;
}
lastOffset++;
while (lastOffset < offset) {
var m = lastOffset + (offset - lastOffset >>> 1);
if (compare(value, array[start + m]) < 0) {
offset = m;
} else {
lastOffset = m + 1;
}
}
return offset;
}
var TimSort = (function () {
function TimSort(array, compare) {
_classCallCheck(this, TimSort);
this.array = null;
this.compare = null;
this.minGallop = DEFAULT_MIN_GALLOPING;
this.length = 0;
this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH;
this.stackLength = 0;
this.runStart = null;
this.runLength = null;
this.stackSize = 0;
this.array = array;
this.compare = compare;
this.length = array.length;
if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) {
this.tmpStorageLength = this.length >>> 1;
}
this.tmp = new Array(this.tmpStorageLength);
this.stackLength = this.length < 120 ? 5 : this.length < 1542 ? 10 : this.length < 119151 ? 19 : 40;
this.runStart = new Array(this.stackLength);
this.runLength = new Array(this.stackLength);
}
TimSort.prototype.pushRun = function pushRun(runStart, runLength) {
this.runStart[this.stackSize] = runStart;
this.runLength[this.stackSize] = runLength;
this.stackSize += 1;
};
TimSort.prototype.mergeRuns = function mergeRuns() {
while (this.stackSize > 1) {
var n = this.stackSize - 2;
if (n >= 1 && this.runLength[n - 1] <= this.runLength[n] + this.runLength[n + 1] || n >= 2 && this.runLength[n - 2] <= this.runLength[n] + this.runLength[n - 1]) {
if (this.runLength[n - 1] < this.runLength[n + 1]) {
n--;
}
} else if (this.runLength[n] > this.runLength[n + 1]) {
break;
}
this.mergeAt(n);
}
};
TimSort.prototype.forceMergeRuns = function forceMergeRuns() {
while (this.stackSize > 1) {
var n = this.stackSize - 2;
if (n > 0 && this.runLength[n - 1] < this.runLength[n + 1]) {
n--;
}
this.mergeAt(n);
}
};
TimSort.prototype.mergeAt = function mergeAt(i) {
var compare = this.compare;
var array = this.array;
var start1 = this.runStart[i];
var length1 = this.runLength[i];
var start2 = this.runStart[i + 1];
var length2 = this.runLength[i + 1];
this.runLength[i] = length1 + length2;
if (i === this.stackSize - 3) {
this.runStart[i + 1] = this.runStart[i + 2];
this.runLength[i + 1] = this.runLength[i + 2];
}
this.stackSize--;
var k = gallopRight(array[start2], array, start1, length1, 0, compare);
start1 += k;
length1 -= k;
if (length1 === 0) {
return;
}
length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);
if (length2 === 0) {
return;
}
if (length1 <= length2) {
this.mergeLow(start1, length1, start2, length2);
} else {
this.mergeHigh(start1, length1, start2, length2);
}
};
TimSort.prototype.mergeLow = function mergeLow(start1, length1, start2, length2) {
var compare = this.compare;
var array = this.array;
var tmp = this.tmp;
var i = 0;
for (i = 0; i < length1; i++) {
tmp[i] = array[start1 + i];
}
var cursor1 = 0;
var cursor2 = start2;
var dest = start1;
array[dest++] = array[cursor2++];
if (--length2 === 0) {
for (i = 0; i < length1; i++) {
array[dest + i] = tmp[cursor1 + i];
}
return;
}
if (length1 === 1) {
for (i = 0; i < length2; i++) {
array[dest + i] = array[cursor2 + i];
}
array[dest + length2] = tmp[cursor1];
return;
}
var minGallop = this.minGallop;
while (true) {
var count1 = 0;
var count2 = 0;
var exit = false;
do {
if (compare(array[cursor2], tmp[cursor1]) < 0) {
array[dest++] = array[cursor2++];
count2++;
count1 = 0;
if (--length2 === 0) {
exit = true;
break;
}
} else {
array[dest++] = tmp[cursor1++];
count1++;
count2 = 0;
if (--length1 === 1) {
exit = true;
break;
}
}
} while ((count1 | count2) < minGallop);
if (exit) {
break;
}
do {
count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);
if (count1 !== 0) {
for (i = 0; i < count1; i++) {
array[dest + i] = tmp[cursor1 + i];
}
dest += count1;
cursor1 += count1;
length1 -= count1;
if (length1 <= 1) {
exit = true;
break;
}
}
array[dest++] = array[cursor2++];
if (--length2 === 0) {
exit = true;
break;
}
count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);
if (count2 !== 0) {
for (i = 0; i < count2; i++) {
array[dest + i] = array[cursor2 + i];
}
dest += count2;
cursor2 += count2;
length2 -= count2;
if (length2 === 0) {
exit = true;
break;
}
}
array[dest++] = tmp[cursor1++];
if (--length1 === 1) {
exit = true;
break;
}
minGallop--;
} while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
if (exit) {
break;
}
if (minGallop < 0) {
minGallop = 0;
}
minGallop += 2;
}
this.minGallop = minGallop;
if (minGallop < 1) {
this.minGallop = 1;
}
if (length1 === 1) {
for (i = 0; i < length2; i++) {
array[dest + i] = array[cursor2 + i];
}
array[dest + length2] = tmp[cursor1];
} else if (length1 === 0) {
throw new Error('mergeLow preconditions were not respected');
} else {
for (i = 0; i < length1; i++) {
array[dest + i] = tmp[cursor1 + i];
}
}
};
TimSort.prototype.mergeHigh = function mergeHigh(start1, length1, start2, length2) {
var compare = this.compare;
var array = this.array;
var tmp = this.tmp;
var i = 0;
for (i = 0; i < length2; i++) {
tmp[i] = array[start2 + i];
}
var cursor1 = start1 + length1 - 1;
var cursor2 = length2 - 1;
var dest = start2 + length2 - 1;
var customCursor = 0;
var customDest = 0;
array[dest--] = array[cursor1--];
if (--length1 === 0) {
customCursor = dest - (length2 - 1);
for (i = 0; i < length2; i++) {
array[customCursor + i] = tmp[i];
}
return;
}
if (length2 === 1) {
dest -= length1;
cursor1 -= length1;
customDest = dest + 1;
customCursor = cursor1 + 1;
for (i = length1 - 1; i >= 0; i--) {
array[customDest + i] = array[customCursor + i];
}
array[dest] = tmp[cursor2];
return;
}
var minGallop = this.minGallop;
while (true) {
var count1 = 0;
var count2 = 0;
var exit = false;
do {
if (compare(tmp[cursor2], array[cursor1]) < 0) {
array[dest--] = array[cursor1--];
count1++;
count2 = 0;
if (--length1 === 0) {
exit = true;
break;
}
} else {
array[dest--] = tmp[cursor2--];
count2++;
count1 = 0;
if (--length2 === 1) {
exit = true;
break;
}
}
} while ((count1 | count2) < minGallop);
if (exit) {
break;
}
do {
count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);
if (count1 !== 0) {
dest -= count1;
cursor1 -= count1;
length1 -= count1;
customDest = dest + 1;
customCursor = cursor1 + 1;
for (i = count1 - 1; i >= 0; i--) {
array[customDest + i] = array[customCursor + i];
}
if (length1 === 0) {
exit = true;
break;
}
}
array[dest--] = tmp[cursor2--];
if (--length2 === 1) {
exit = true;
break;
}
count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);
if (count2 !== 0) {
dest -= count2;
cursor2 -= count2;
length2 -= count2;
customDest = dest + 1;
customCursor = cursor2 + 1;
for (i = 0; i < count2; i++) {
array[customDest + i] = tmp[customCursor + i];
}
if (length2 <= 1) {
exit = true;
break;
}
}
array[dest--] = array[cursor1--];
if (--length1 === 0) {
exit = true;
break;
}
minGallop--;
} while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
if (exit) {
break;
}
if (minGallop < 0) {
minGallop = 0;
}
minGallop += 2;
}
this.minGallop = minGallop;
if (minGallop < 1) {
this.minGallop = 1;
}
if (length2 === 1) {
dest -= length1;
cursor1 -= length1;
customDest = dest + 1;
customCursor = cursor1 + 1;
for (i = length1 - 1; i >= 0; i--) {
array[customDest + i] = array[customCursor + i];
}
array[dest] = tmp[cursor2];
} else if (length2 === 0) {
throw new Error('mergeHigh preconditions were not respected');
} else {
customCursor = dest - (length2 - 1);
for (i = 0; i < length2; i++) {
array[customCursor + i] = tmp[i];
}
}
};
return TimSort;
})();
function sort(array, compare, lo, hi) {
if (!Array.isArray(array)) {
throw new TypeError('Can only sort arrays');
}
if (!compare) {
compare = alphabeticalCompare;
} else if (typeof compare !== 'function') {
hi = lo;
lo = compare;
compare = alphabeticalCompare;
}
if (!lo) {
lo = 0;
}
if (!hi) {
hi = array.length;
}
var remaining = hi - lo;
if (remaining < 2) {
return;
}
var runLength = 0;
if (remaining < DEFAULT_MIN_MERGE) {
runLength = makeAscendingRun(array, lo, hi, compare);
binaryInsertionSort(array, lo, hi, lo + runLength, compare);
return;
}
var ts = new TimSort(array, compare);
var minRun = minRunLength(remaining);
do {
runLength = makeAscendingRun(array, lo, hi, compare);
if (runLength < minRun) {
var force = remaining;
if (force > minRun) {
force = minRun;
}
binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
runLength = force;
}
ts.pushRun(lo, runLength);
ts.mergeRuns();
remaining -= runLength;
lo += runLength;
} while (remaining !== 0);
ts.forceMergeRuns();
}
});

1
assets_old/node_modules/timsort/build/timsort.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1
assets_old/node_modules/timsort/index.js generated vendored Normal file
View file

@ -0,0 +1 @@
module.exports = require('./build/timsort.js');

48
assets_old/node_modules/timsort/package.json generated vendored Normal file
View file

@ -0,0 +1,48 @@
{
"name": "timsort",
"version": "0.3.0",
"author": {
"name": "Marco Ziccardi",
"url": "http://mziccard.me/"
},
"description": "TimSort: Fast Sorting for Node.js",
"homepage": "https://github.com/mziccard/node-timsort",
"main": "index.js",
"directories": {
"test": "./test",
"benchmark": "./benchmark"
},
"dependencies": {},
"devDependencies": {
"assert": "~1.3.0",
"babel-eslint": "^4.0.5",
"eslint": "^1.1.0",
"grunt": "^0.4.5",
"grunt-babel": "^5.0.1",
"grunt-banner": "^0.5.0",
"grunt-contrib-clean": "^0.6.0",
"grunt-contrib-uglify": "^0.9.1",
"mocha": "~2.2.5"
},
"scripts": {
"test": "mocha --timeout 5000",
"lint": "eslint Gruntfile.js src/ test/ benchmark/index.js",
"benchmark": "node benchmark/index.js"
},
"repository": {
"type": "git",
"url": "https://github.com/mziccard/node-timsort.git"
},
"keywords": [
"sort",
"compare",
"TimSort",
"algorithm",
"python",
"performance"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/mziccard/node-timsort/issues"
}
}

977
assets_old/node_modules/timsort/src/timsort.js generated vendored Normal file
View file

@ -0,0 +1,977 @@
/**
* Default minimum size of a run.
*/
const DEFAULT_MIN_MERGE = 32;
/**
* Minimum ordered subsequece required to do galloping.
*/
const DEFAULT_MIN_GALLOPING = 7;
/**
* Default tmp storage length. Can increase depending on the size of the
* smallest run to merge.
*/
const DEFAULT_TMP_STORAGE_LENGTH = 256;
/**
* Pre-computed powers of 10 for efficient lexicographic comparison of
* small integers.
*/
const POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9]
/**
* Estimate the logarithm base 10 of a small integer.
*
* @param {number} x - The integer to estimate the logarithm of.
* @return {number} - The estimated logarithm of the integer.
*/
function log10(x) {
if (x < 1e5) {
if (x < 1e2) {
return x < 1e1 ? 0 : 1;
}
if (x < 1e4) {
return x < 1e3 ? 2 : 3;
}
return 4;
}
if (x < 1e7) {
return x < 1e6 ? 5 : 6;
}
if (x < 1e9) {
return x < 1e8 ? 7 : 8;
}
return 9;
}
/**
* Default alphabetical comparison of items.
*
* @param {string|object|number} a - First element to compare.
* @param {string|object|number} b - Second element to compare.
* @return {number} - A positive number if a.toString() > b.toString(), a
* negative number if .toString() < b.toString(), 0 otherwise.
*/
function alphabeticalCompare(a, b) {
if (a === b) {
return 0;
}
if (~~a === a && ~~b === b) {
if (a === 0 || b === 0) {
return a < b ? -1 : 1;
}
if (a < 0 || b < 0) {
if (b >= 0) {
return -1;
}
if (a >= 0) {
return 1;
}
a = -a;
b = -b;
}
const al = log10(a);
const bl = log10(b);
let t = 0;
if (al < bl) {
a *= POWERS_OF_TEN[bl - al - 1];
b /= 10;
t = -1;
} else if (al > bl) {
b *= POWERS_OF_TEN[al - bl - 1];
a /= 10;
t = 1;
}
if (a === b) {
return t;
}
return a < b ? -1 : 1;
}
let aStr = String(a);
let bStr = String(b);
if (aStr === bStr) {
return 0;
}
return aStr < bStr ? -1 : 1;
}
/**
* Compute minimum run length for TimSort
*
* @param {number} n - The size of the array to sort.
*/
function minRunLength(n) {
let r = 0;
while (n >= DEFAULT_MIN_MERGE) {
r |= (n & 1);
n >>= 1;
}
return n + r;
}
/**
* Counts the length of a monotonically ascending or strictly monotonically
* descending sequence (run) starting at array[lo] in the range [lo, hi). If
* the run is descending it is made ascending.
*
* @param {array} array - The array to reverse.
* @param {number} lo - First element in the range (inclusive).
* @param {number} hi - Last element in the range.
* @param {function} compare - Item comparison function.
* @return {number} - The length of the run.
*/
function makeAscendingRun(array, lo, hi, compare) {
let runHi = lo + 1;
if (runHi === hi) {
return 1;
}
// Descending
if (compare(array[runHi++], array[lo]) < 0) {
while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
runHi++;
}
reverseRun(array, lo, runHi);
// Ascending
} else {
while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
runHi++;
}
}
return runHi - lo;
}
/**
* Reverse an array in the range [lo, hi).
*
* @param {array} array - The array to reverse.
* @param {number} lo - First element in the range (inclusive).
* @param {number} hi - Last element in the range.
*/
function reverseRun(array, lo, hi) {
hi--;
while (lo < hi) {
let t = array[lo];
array[lo++] = array[hi];
array[hi--] = t;
}
}
/**
* Perform the binary sort of the array in the range [lo, hi) where start is
* the first element possibly out of order.
*
* @param {array} array - The array to sort.
* @param {number} lo - First element in the range (inclusive).
* @param {number} hi - Last element in the range.
* @param {number} start - First element possibly out of order.
* @param {function} compare - Item comparison function.
*/
function binaryInsertionSort(array, lo, hi, start, compare) {
if (start === lo) {
start++;
}
for (; start < hi; start++) {
let pivot = array[start];
// Ranges of the array where pivot belongs
let left = lo;
let right = start;
/*
* pivot >= array[i] for i in [lo, left)
* pivot < array[i] for i in in [right, start)
*/
while (left < right) {
let mid = (left + right) >>> 1;
if (compare(pivot, array[mid]) < 0) {
right = mid;
} else {
left = mid + 1;
}
}
/*
* Move elements right to make room for the pivot. If there are elements
* equal to pivot, left points to the first slot after them: this is also
* a reason for which TimSort is stable
*/
let n = start - left;
// Switch is just an optimization for small arrays
switch (n) {
case 3:
array[left + 3] = array[left + 2];
/* falls through */
case 2:
array[left + 2] = array[left + 1];
/* falls through */
case 1:
array[left + 1] = array[left];
break;
default:
while (n > 0) {
array[left + n] = array[left + n - 1];
n--;
}
}
array[left] = pivot;
}
}
/**
* Find the position at which to insert a value in a sorted range. If the range
* contains elements equal to the value the leftmost element index is returned
* (for stability).
*
* @param {number} value - Value to insert.
* @param {array} array - The array in which to insert value.
* @param {number} start - First element in the range.
* @param {number} length - Length of the range.
* @param {number} hint - The index at which to begin the search.
* @param {function} compare - Item comparison function.
* @return {number} - The index where to insert value.
*/
function gallopLeft(value, array, start, length, hint, compare) {
let lastOffset = 0;
let maxOffset = 0;
let offset = 1;
if (compare(value, array[start + hint]) > 0) {
maxOffset = length - hint;
while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
// Make offsets relative to start
lastOffset += hint;
offset += hint;
// value <= array[start + hint]
} else {
maxOffset = hint + 1;
while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
// Make offsets relative to start
let tmp = lastOffset;
lastOffset = hint - offset;
offset = hint - tmp;
}
/*
* Now array[start+lastOffset] < value <= array[start+offset], so value
* belongs somewhere in the range (start + lastOffset, start + offset]. Do a
* binary search, with invariant array[start + lastOffset - 1] < value <=
* array[start + offset].
*/
lastOffset++;
while (lastOffset < offset) {
let m = lastOffset + ((offset - lastOffset) >>> 1);
if (compare(value, array[start + m]) > 0) {
lastOffset = m + 1;
} else {
offset = m;
}
}
return offset;
}
/**
* Find the position at which to insert a value in a sorted range. If the range
* contains elements equal to the value the rightmost element index is returned
* (for stability).
*
* @param {number} value - Value to insert.
* @param {array} array - The array in which to insert value.
* @param {number} start - First element in the range.
* @param {number} length - Length of the range.
* @param {number} hint - The index at which to begin the search.
* @param {function} compare - Item comparison function.
* @return {number} - The index where to insert value.
*/
function gallopRight(value, array, start, length, hint, compare) {
let lastOffset = 0;
let maxOffset = 0;
let offset = 1;
if (compare(value, array[start + hint]) < 0) {
maxOffset = hint + 1;
while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
// Make offsets relative to start
let tmp = lastOffset;
lastOffset = hint - offset;
offset = hint - tmp;
// value >= array[start + hint]
} else {
maxOffset = length - hint;
while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
lastOffset = offset;
offset = (offset << 1) + 1;
if (offset <= 0) {
offset = maxOffset;
}
}
if (offset > maxOffset) {
offset = maxOffset;
}
// Make offsets relative to start
lastOffset += hint;
offset += hint;
}
/*
* Now array[start+lastOffset] < value <= array[start+offset], so value
* belongs somewhere in the range (start + lastOffset, start + offset]. Do a
* binary search, with invariant array[start + lastOffset - 1] < value <=
* array[start + offset].
*/
lastOffset++;
while (lastOffset < offset) {
let m = lastOffset + ((offset - lastOffset) >>> 1);
if (compare(value, array[start + m]) < 0) {
offset = m;
} else {
lastOffset = m + 1;
}
}
return offset;
}
class TimSort {
array = null;
compare = null;
minGallop = DEFAULT_MIN_GALLOPING;
length = 0;
tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH;
stackLength = 0;
runStart = null;
runLength = null;
stackSize = 0;
constructor(array, compare) {
this.array = array;
this.compare = compare;
this.length = array.length;
if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) {
this.tmpStorageLength = this.length >>> 1;
}
this.tmp = new Array(this.tmpStorageLength);
this.stackLength =
(this.length < 120 ? 5 :
this.length < 1542 ? 10 :
this.length < 119151 ? 19 : 40);
this.runStart = new Array(this.stackLength);
this.runLength = new Array(this.stackLength);
}
/**
* Push a new run on TimSort's stack.
*
* @param {number} runStart - Start index of the run in the original array.
* @param {number} runLength - Length of the run;
*/
pushRun(runStart, runLength) {
this.runStart[this.stackSize] = runStart;
this.runLength[this.stackSize] = runLength;
this.stackSize += 1;
}
/**
* Merge runs on TimSort's stack so that the following holds for all i:
* 1) runLength[i - 3] > runLength[i - 2] + runLength[i - 1]
* 2) runLength[i - 2] > runLength[i - 1]
*/
mergeRuns() {
while (this.stackSize > 1) {
let n = this.stackSize - 2;
if ((n >= 1 &&
this.runLength[n - 1] <= this.runLength[n] + this.runLength[n + 1]) ||
(n >= 2 &&
this.runLength[n - 2] <= this.runLength[n] + this.runLength[n - 1])) {
if (this.runLength[n - 1] < this.runLength[n + 1]) {
n--;
}
} else if (this.runLength[n] > this.runLength[n + 1]) {
break;
}
this.mergeAt(n);
}
}
/**
* Merge all runs on TimSort's stack until only one remains.
*/
forceMergeRuns() {
while (this.stackSize > 1) {
let n = this.stackSize - 2;
if (n > 0 && this.runLength[n - 1] < this.runLength[n + 1]) {
n--;
}
this.mergeAt(n);
}
}
/**
* Merge the runs on the stack at positions i and i+1. Must be always be called
* with i=stackSize-2 or i=stackSize-3 (that is, we merge on top of the stack).
*
* @param {number} i - Index of the run to merge in TimSort's stack.
*/
mergeAt(i) {
let compare = this.compare;
let array = this.array;
let start1 = this.runStart[i];
let length1 = this.runLength[i];
let start2 = this.runStart[i + 1];
let length2 = this.runLength[i + 1];
this.runLength[i] = length1 + length2;
if (i === this.stackSize - 3) {
this.runStart[i + 1] = this.runStart[i + 2];
this.runLength[i + 1] = this.runLength[i + 2];
}
this.stackSize--;
/*
* Find where the first element in the second run goes in run1. Previous
* elements in run1 are already in place
*/
let k = gallopRight(array[start2], array, start1, length1, 0, compare);
start1 += k;
length1 -= k;
if (length1 === 0) {
return;
}
/*
* Find where the last element in the first run goes in run2. Next elements
* in run2 are already in place
*/
length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);
if (length2 === 0) {
return;
}
/*
* Merge remaining runs. A tmp array with length = min(length1, length2) is
* used
*/
if (length1 <= length2) {
this.mergeLow(start1, length1, start2, length2);
} else {
this.mergeHigh(start1, length1, start2, length2);
}
}
/**
* Merge two adjacent runs in a stable way. The runs must be such that the
* first element of run1 is bigger than the first element in run2 and the
* last element of run1 is greater than all the elements in run2.
* The method should be called when run1.length <= run2.length as it uses
* TimSort temporary array to store run1. Use mergeHigh if run1.length >
* run2.length.
*
* @param {number} start1 - First element in run1.
* @param {number} length1 - Length of run1.
* @param {number} start2 - First element in run2.
* @param {number} length2 - Length of run2.
*/
mergeLow(start1, length1, start2, length2) {
let compare = this.compare;
let array = this.array;
let tmp = this.tmp;
let i = 0;
for (i = 0; i < length1; i++) {
tmp[i] = array[start1 + i];
}
let cursor1 = 0;
let cursor2 = start2;
let dest = start1;
array[dest++] = array[cursor2++];
if (--length2 === 0) {
for (i = 0; i < length1; i++) {
array[dest + i] = tmp[cursor1 + i];
}
return;
}
if (length1 === 1) {
for (i = 0; i < length2; i++) {
array[dest + i] = array[cursor2 + i];
}
array[dest + length2] = tmp[cursor1];
return;
}
let minGallop = this.minGallop;
while (true) {
let count1 = 0;
let count2 = 0;
let exit = false;
do {
if (compare(array[cursor2], tmp[cursor1]) < 0) {
array[dest++] = array[cursor2++];
count2++;
count1 = 0;
if (--length2 === 0) {
exit = true;
break;
}
} else {
array[dest++] = tmp[cursor1++];
count1++;
count2 = 0;
if (--length1 === 1) {
exit = true;
break;
}
}
} while ((count1 | count2) < minGallop);
if (exit) {
break;
}
do {
count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);
if (count1 !== 0) {
for (i = 0; i < count1; i++) {
array[dest + i] = tmp[cursor1 + i];
}
dest += count1;
cursor1 += count1;
length1 -= count1;
if (length1 <= 1) {
exit = true;
break;
}
}
array[dest++] = array[cursor2++];
if (--length2 === 0) {
exit = true;
break;
}
count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);
if (count2 !== 0) {
for (i = 0; i < count2; i++) {
array[dest + i] = array[cursor2 + i];
}
dest += count2;
cursor2 += count2;
length2 -= count2;
if (length2 === 0) {
exit = true;
break;
}
}
array[dest++] = tmp[cursor1++];
if (--length1 === 1) {
exit = true;
break;
}
minGallop--;
} while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
if (exit) {
break;
}
if (minGallop < 0) {
minGallop = 0;
}
minGallop += 2;
}
this.minGallop = minGallop;
if (minGallop < 1) {
this.minGallop = 1;
}
if (length1 === 1) {
for (i = 0; i < length2; i++) {
array[dest + i] = array[cursor2 + i];
}
array[dest + length2] = tmp[cursor1];
} else if (length1 === 0) {
throw new Error('mergeLow preconditions were not respected');
} else {
for (i = 0; i < length1; i++) {
array[dest + i] = tmp[cursor1 + i];
}
}
}
/**
* Merge two adjacent runs in a stable way. The runs must be such that the
* first element of run1 is bigger than the first element in run2 and the
* last element of run1 is greater than all the elements in run2.
* The method should be called when run1.length > run2.length as it uses
* TimSort temporary array to store run2. Use mergeLow if run1.length <=
* run2.length.
*
* @param {number} start1 - First element in run1.
* @param {number} length1 - Length of run1.
* @param {number} start2 - First element in run2.
* @param {number} length2 - Length of run2.
*/
mergeHigh(start1, length1, start2, length2) {
let compare = this.compare;
let array = this.array;
let tmp = this.tmp;
let i = 0;
for (i = 0; i < length2; i++) {
tmp[i] = array[start2 + i];
}
let cursor1 = start1 + length1 - 1;
let cursor2 = length2 - 1;
let dest = start2 + length2 - 1;
let customCursor = 0;
let customDest = 0;
array[dest--] = array[cursor1--];
if (--length1 === 0) {
customCursor = dest - (length2 - 1);
for (i = 0; i < length2; i++) {
array[customCursor + i] = tmp[i];
}
return;
}
if (length2 === 1) {
dest -= length1;
cursor1 -= length1;
customDest = dest + 1;
customCursor = cursor1 + 1;
for (i = length1 - 1; i >= 0; i--) {
array[customDest + i] = array[customCursor + i];
}
array[dest] = tmp[cursor2];
return;
}
let minGallop = this.minGallop;
while (true) {
let count1 = 0;
let count2 = 0;
let exit = false;
do {
if (compare(tmp[cursor2], array[cursor1]) < 0) {
array[dest--] = array[cursor1--];
count1++;
count2 = 0;
if (--length1 === 0) {
exit = true;
break;
}
} else {
array[dest--] = tmp[cursor2--];
count2++;
count1 = 0;
if (--length2 === 1) {
exit = true;
break;
}
}
} while ((count1 | count2) < minGallop);
if (exit) {
break;
}
do {
count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);
if (count1 !== 0) {
dest -= count1;
cursor1 -= count1;
length1 -= count1;
customDest = dest + 1;
customCursor = cursor1 + 1;
for (i = count1 - 1; i >= 0; i--) {
array[customDest + i] = array[customCursor + i];
}
if (length1 === 0) {
exit = true;
break;
}
}
array[dest--] = tmp[cursor2--];
if (--length2 === 1) {
exit = true;
break;
}
count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);
if (count2 !== 0) {
dest -= count2;
cursor2 -= count2;
length2 -= count2;
customDest = dest + 1;
customCursor = cursor2 + 1;
for (i = 0; i < count2; i++) {
array[customDest + i] = tmp[customCursor + i];
}
if (length2 <= 1) {
exit = true;
break;
}
}
array[dest--] = array[cursor1--];
if (--length1 === 0) {
exit = true;
break;
}
minGallop--;
} while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
if (exit) {
break;
}
if (minGallop < 0) {
minGallop = 0;
}
minGallop += 2;
}
this.minGallop = minGallop;
if (minGallop < 1) {
this.minGallop = 1;
}
if (length2 === 1) {
dest -= length1;
cursor1 -= length1;
customDest = dest + 1;
customCursor = cursor1 + 1;
for (i = length1 - 1; i >= 0; i--) {
array[customDest + i] = array[customCursor + i];
}
array[dest] = tmp[cursor2];
} else if (length2 === 0) {
throw new Error('mergeHigh preconditions were not respected');
} else {
customCursor = dest - (length2 - 1);
for (i = 0; i < length2; i++) {
array[customCursor + i] = tmp[i];
}
}
}
}
/**
* Sort an array in the range [lo, hi) using TimSort.
*
* @param {array} array - The array to sort.
* @param {function=} compare - Item comparison function. Default is
* alphabetical
* @param {number} lo - First element in the range (inclusive).
* @param {number} hi - Last element in the range.
* comparator.
*/
export function sort(array, compare, lo, hi) {
if (!Array.isArray(array)) {
throw new TypeError('Can only sort arrays');
}
/*
* Handle the case where a comparison function is not provided. We do
* lexicographic sorting
*/
if (!compare) {
compare = alphabeticalCompare;
} else if (typeof compare !== 'function') {
hi = lo;
lo = compare;
compare = alphabeticalCompare;
}
if (!lo) {
lo = 0;
}
if (!hi) {
hi = array.length;
}
let remaining = hi - lo;
// The array is already sorted
if (remaining < 2) {
return;
}
let runLength = 0;
// On small arrays binary sort can be used directly
if (remaining < DEFAULT_MIN_MERGE) {
runLength = makeAscendingRun(array, lo, hi, compare);
binaryInsertionSort(array, lo, hi, lo + runLength, compare);
return;
}
let ts = new TimSort(array, compare);
let minRun = minRunLength(remaining);
do {
runLength = makeAscendingRun(array, lo, hi, compare);
if (runLength < minRun) {
let force = remaining;
if (force > minRun) {
force = minRun;
}
binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
runLength = force;
}
// Push new run and merge if necessary
ts.pushRun(lo, runLength);
ts.mergeRuns();
// Go find next run
remaining -= runLength;
lo += runLength;
} while (remaining !== 0);
// Force merging of remaining runs
ts.forceMergeRuns();
}