source: trip-planner-front/node_modules/timsort/build/timsort.js@ bdd6491

Last change on this file since bdd6491 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 18.3 KB
Line 
1/****
2 * The MIT License
3 *
4 * Copyright (c) 2015 Marco Ziccardi
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 ****/
25(function (global, factory) {
26 if (typeof define === 'function' && define.amd) {
27 define('timsort', ['exports'], factory);
28 } else if (typeof exports !== 'undefined') {
29 factory(exports);
30 } else {
31 var mod = {
32 exports: {}
33 };
34 factory(mod.exports);
35 global.timsort = mod.exports;
36 }
37})(this, function (exports) {
38 'use strict';
39
40 exports.__esModule = true;
41 exports.sort = sort;
42
43 function _classCallCheck(instance, Constructor) {
44 if (!(instance instanceof Constructor)) {
45 throw new TypeError('Cannot call a class as a function');
46 }
47 }
48
49 var DEFAULT_MIN_MERGE = 32;
50
51 var DEFAULT_MIN_GALLOPING = 7;
52
53 var DEFAULT_TMP_STORAGE_LENGTH = 256;
54
55 var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9];
56
57 function log10(x) {
58 if (x < 1e5) {
59 if (x < 1e2) {
60 return x < 1e1 ? 0 : 1;
61 }
62
63 if (x < 1e4) {
64 return x < 1e3 ? 2 : 3;
65 }
66
67 return 4;
68 }
69
70 if (x < 1e7) {
71 return x < 1e6 ? 5 : 6;
72 }
73
74 if (x < 1e9) {
75 return x < 1e8 ? 7 : 8;
76 }
77
78 return 9;
79 }
80
81 function alphabeticalCompare(a, b) {
82 if (a === b) {
83 return 0;
84 }
85
86 if (~ ~a === a && ~ ~b === b) {
87 if (a === 0 || b === 0) {
88 return a < b ? -1 : 1;
89 }
90
91 if (a < 0 || b < 0) {
92 if (b >= 0) {
93 return -1;
94 }
95
96 if (a >= 0) {
97 return 1;
98 }
99
100 a = -a;
101 b = -b;
102 }
103
104 var al = log10(a);
105 var bl = log10(b);
106
107 var t = 0;
108
109 if (al < bl) {
110 a *= POWERS_OF_TEN[bl - al - 1];
111 b /= 10;
112 t = -1;
113 } else if (al > bl) {
114 b *= POWERS_OF_TEN[al - bl - 1];
115 a /= 10;
116 t = 1;
117 }
118
119 if (a === b) {
120 return t;
121 }
122
123 return a < b ? -1 : 1;
124 }
125
126 var aStr = String(a);
127 var bStr = String(b);
128
129 if (aStr === bStr) {
130 return 0;
131 }
132
133 return aStr < bStr ? -1 : 1;
134 }
135
136 function minRunLength(n) {
137 var r = 0;
138
139 while (n >= DEFAULT_MIN_MERGE) {
140 r |= n & 1;
141 n >>= 1;
142 }
143
144 return n + r;
145 }
146
147 function makeAscendingRun(array, lo, hi, compare) {
148 var runHi = lo + 1;
149
150 if (runHi === hi) {
151 return 1;
152 }
153
154 if (compare(array[runHi++], array[lo]) < 0) {
155 while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
156 runHi++;
157 }
158
159 reverseRun(array, lo, runHi);
160 } else {
161 while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
162 runHi++;
163 }
164 }
165
166 return runHi - lo;
167 }
168
169 function reverseRun(array, lo, hi) {
170 hi--;
171
172 while (lo < hi) {
173 var t = array[lo];
174 array[lo++] = array[hi];
175 array[hi--] = t;
176 }
177 }
178
179 function binaryInsertionSort(array, lo, hi, start, compare) {
180 if (start === lo) {
181 start++;
182 }
183
184 for (; start < hi; start++) {
185 var pivot = array[start];
186
187 var left = lo;
188 var right = start;
189
190 while (left < right) {
191 var mid = left + right >>> 1;
192
193 if (compare(pivot, array[mid]) < 0) {
194 right = mid;
195 } else {
196 left = mid + 1;
197 }
198 }
199
200 var n = start - left;
201
202 switch (n) {
203 case 3:
204 array[left + 3] = array[left + 2];
205
206 case 2:
207 array[left + 2] = array[left + 1];
208
209 case 1:
210 array[left + 1] = array[left];
211 break;
212 default:
213 while (n > 0) {
214 array[left + n] = array[left + n - 1];
215 n--;
216 }
217 }
218
219 array[left] = pivot;
220 }
221 }
222
223 function gallopLeft(value, array, start, length, hint, compare) {
224 var lastOffset = 0;
225 var maxOffset = 0;
226 var offset = 1;
227
228 if (compare(value, array[start + hint]) > 0) {
229 maxOffset = length - hint;
230
231 while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
232 lastOffset = offset;
233 offset = (offset << 1) + 1;
234
235 if (offset <= 0) {
236 offset = maxOffset;
237 }
238 }
239
240 if (offset > maxOffset) {
241 offset = maxOffset;
242 }
243
244 lastOffset += hint;
245 offset += hint;
246 } else {
247 maxOffset = hint + 1;
248 while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
249 lastOffset = offset;
250 offset = (offset << 1) + 1;
251
252 if (offset <= 0) {
253 offset = maxOffset;
254 }
255 }
256 if (offset > maxOffset) {
257 offset = maxOffset;
258 }
259
260 var tmp = lastOffset;
261 lastOffset = hint - offset;
262 offset = hint - tmp;
263 }
264
265 lastOffset++;
266 while (lastOffset < offset) {
267 var m = lastOffset + (offset - lastOffset >>> 1);
268
269 if (compare(value, array[start + m]) > 0) {
270 lastOffset = m + 1;
271 } else {
272 offset = m;
273 }
274 }
275 return offset;
276 }
277
278 function gallopRight(value, array, start, length, hint, compare) {
279 var lastOffset = 0;
280 var maxOffset = 0;
281 var offset = 1;
282
283 if (compare(value, array[start + hint]) < 0) {
284 maxOffset = hint + 1;
285
286 while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
287 lastOffset = offset;
288 offset = (offset << 1) + 1;
289
290 if (offset <= 0) {
291 offset = maxOffset;
292 }
293 }
294
295 if (offset > maxOffset) {
296 offset = maxOffset;
297 }
298
299 var tmp = lastOffset;
300 lastOffset = hint - offset;
301 offset = hint - tmp;
302 } else {
303 maxOffset = length - hint;
304
305 while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
306 lastOffset = offset;
307 offset = (offset << 1) + 1;
308
309 if (offset <= 0) {
310 offset = maxOffset;
311 }
312 }
313
314 if (offset > maxOffset) {
315 offset = maxOffset;
316 }
317
318 lastOffset += hint;
319 offset += hint;
320 }
321
322 lastOffset++;
323
324 while (lastOffset < offset) {
325 var m = lastOffset + (offset - lastOffset >>> 1);
326
327 if (compare(value, array[start + m]) < 0) {
328 offset = m;
329 } else {
330 lastOffset = m + 1;
331 }
332 }
333
334 return offset;
335 }
336
337 var TimSort = (function () {
338 function TimSort(array, compare) {
339 _classCallCheck(this, TimSort);
340
341 this.array = null;
342 this.compare = null;
343 this.minGallop = DEFAULT_MIN_GALLOPING;
344 this.length = 0;
345 this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH;
346 this.stackLength = 0;
347 this.runStart = null;
348 this.runLength = null;
349 this.stackSize = 0;
350
351 this.array = array;
352 this.compare = compare;
353
354 this.length = array.length;
355
356 if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) {
357 this.tmpStorageLength = this.length >>> 1;
358 }
359
360 this.tmp = new Array(this.tmpStorageLength);
361
362 this.stackLength = this.length < 120 ? 5 : this.length < 1542 ? 10 : this.length < 119151 ? 19 : 40;
363
364 this.runStart = new Array(this.stackLength);
365 this.runLength = new Array(this.stackLength);
366 }
367
368 TimSort.prototype.pushRun = function pushRun(runStart, runLength) {
369 this.runStart[this.stackSize] = runStart;
370 this.runLength[this.stackSize] = runLength;
371 this.stackSize += 1;
372 };
373
374 TimSort.prototype.mergeRuns = function mergeRuns() {
375 while (this.stackSize > 1) {
376 var n = this.stackSize - 2;
377
378 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]) {
379
380 if (this.runLength[n - 1] < this.runLength[n + 1]) {
381 n--;
382 }
383 } else if (this.runLength[n] > this.runLength[n + 1]) {
384 break;
385 }
386 this.mergeAt(n);
387 }
388 };
389
390 TimSort.prototype.forceMergeRuns = function forceMergeRuns() {
391 while (this.stackSize > 1) {
392 var n = this.stackSize - 2;
393
394 if (n > 0 && this.runLength[n - 1] < this.runLength[n + 1]) {
395 n--;
396 }
397
398 this.mergeAt(n);
399 }
400 };
401
402 TimSort.prototype.mergeAt = function mergeAt(i) {
403 var compare = this.compare;
404 var array = this.array;
405
406 var start1 = this.runStart[i];
407 var length1 = this.runLength[i];
408 var start2 = this.runStart[i + 1];
409 var length2 = this.runLength[i + 1];
410
411 this.runLength[i] = length1 + length2;
412
413 if (i === this.stackSize - 3) {
414 this.runStart[i + 1] = this.runStart[i + 2];
415 this.runLength[i + 1] = this.runLength[i + 2];
416 }
417
418 this.stackSize--;
419
420 var k = gallopRight(array[start2], array, start1, length1, 0, compare);
421 start1 += k;
422 length1 -= k;
423
424 if (length1 === 0) {
425 return;
426 }
427
428 length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);
429
430 if (length2 === 0) {
431 return;
432 }
433
434 if (length1 <= length2) {
435 this.mergeLow(start1, length1, start2, length2);
436 } else {
437 this.mergeHigh(start1, length1, start2, length2);
438 }
439 };
440
441 TimSort.prototype.mergeLow = function mergeLow(start1, length1, start2, length2) {
442
443 var compare = this.compare;
444 var array = this.array;
445 var tmp = this.tmp;
446 var i = 0;
447
448 for (i = 0; i < length1; i++) {
449 tmp[i] = array[start1 + i];
450 }
451
452 var cursor1 = 0;
453 var cursor2 = start2;
454 var dest = start1;
455
456 array[dest++] = array[cursor2++];
457
458 if (--length2 === 0) {
459 for (i = 0; i < length1; i++) {
460 array[dest + i] = tmp[cursor1 + i];
461 }
462 return;
463 }
464
465 if (length1 === 1) {
466 for (i = 0; i < length2; i++) {
467 array[dest + i] = array[cursor2 + i];
468 }
469 array[dest + length2] = tmp[cursor1];
470 return;
471 }
472
473 var minGallop = this.minGallop;
474
475 while (true) {
476 var count1 = 0;
477 var count2 = 0;
478 var exit = false;
479
480 do {
481 if (compare(array[cursor2], tmp[cursor1]) < 0) {
482 array[dest++] = array[cursor2++];
483 count2++;
484 count1 = 0;
485
486 if (--length2 === 0) {
487 exit = true;
488 break;
489 }
490 } else {
491 array[dest++] = tmp[cursor1++];
492 count1++;
493 count2 = 0;
494 if (--length1 === 1) {
495 exit = true;
496 break;
497 }
498 }
499 } while ((count1 | count2) < minGallop);
500
501 if (exit) {
502 break;
503 }
504
505 do {
506 count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);
507
508 if (count1 !== 0) {
509 for (i = 0; i < count1; i++) {
510 array[dest + i] = tmp[cursor1 + i];
511 }
512
513 dest += count1;
514 cursor1 += count1;
515 length1 -= count1;
516 if (length1 <= 1) {
517 exit = true;
518 break;
519 }
520 }
521
522 array[dest++] = array[cursor2++];
523
524 if (--length2 === 0) {
525 exit = true;
526 break;
527 }
528
529 count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);
530
531 if (count2 !== 0) {
532 for (i = 0; i < count2; i++) {
533 array[dest + i] = array[cursor2 + i];
534 }
535
536 dest += count2;
537 cursor2 += count2;
538 length2 -= count2;
539
540 if (length2 === 0) {
541 exit = true;
542 break;
543 }
544 }
545 array[dest++] = tmp[cursor1++];
546
547 if (--length1 === 1) {
548 exit = true;
549 break;
550 }
551
552 minGallop--;
553 } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
554
555 if (exit) {
556 break;
557 }
558
559 if (minGallop < 0) {
560 minGallop = 0;
561 }
562
563 minGallop += 2;
564 }
565
566 this.minGallop = minGallop;
567
568 if (minGallop < 1) {
569 this.minGallop = 1;
570 }
571
572 if (length1 === 1) {
573 for (i = 0; i < length2; i++) {
574 array[dest + i] = array[cursor2 + i];
575 }
576 array[dest + length2] = tmp[cursor1];
577 } else if (length1 === 0) {
578 throw new Error('mergeLow preconditions were not respected');
579 } else {
580 for (i = 0; i < length1; i++) {
581 array[dest + i] = tmp[cursor1 + i];
582 }
583 }
584 };
585
586 TimSort.prototype.mergeHigh = function mergeHigh(start1, length1, start2, length2) {
587 var compare = this.compare;
588 var array = this.array;
589 var tmp = this.tmp;
590 var i = 0;
591
592 for (i = 0; i < length2; i++) {
593 tmp[i] = array[start2 + i];
594 }
595
596 var cursor1 = start1 + length1 - 1;
597 var cursor2 = length2 - 1;
598 var dest = start2 + length2 - 1;
599 var customCursor = 0;
600 var customDest = 0;
601
602 array[dest--] = array[cursor1--];
603
604 if (--length1 === 0) {
605 customCursor = dest - (length2 - 1);
606
607 for (i = 0; i < length2; i++) {
608 array[customCursor + i] = tmp[i];
609 }
610
611 return;
612 }
613
614 if (length2 === 1) {
615 dest -= length1;
616 cursor1 -= length1;
617 customDest = dest + 1;
618 customCursor = cursor1 + 1;
619
620 for (i = length1 - 1; i >= 0; i--) {
621 array[customDest + i] = array[customCursor + i];
622 }
623
624 array[dest] = tmp[cursor2];
625 return;
626 }
627
628 var minGallop = this.minGallop;
629
630 while (true) {
631 var count1 = 0;
632 var count2 = 0;
633 var exit = false;
634
635 do {
636 if (compare(tmp[cursor2], array[cursor1]) < 0) {
637 array[dest--] = array[cursor1--];
638 count1++;
639 count2 = 0;
640 if (--length1 === 0) {
641 exit = true;
642 break;
643 }
644 } else {
645 array[dest--] = tmp[cursor2--];
646 count2++;
647 count1 = 0;
648 if (--length2 === 1) {
649 exit = true;
650 break;
651 }
652 }
653 } while ((count1 | count2) < minGallop);
654
655 if (exit) {
656 break;
657 }
658
659 do {
660 count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);
661
662 if (count1 !== 0) {
663 dest -= count1;
664 cursor1 -= count1;
665 length1 -= count1;
666 customDest = dest + 1;
667 customCursor = cursor1 + 1;
668
669 for (i = count1 - 1; i >= 0; i--) {
670 array[customDest + i] = array[customCursor + i];
671 }
672
673 if (length1 === 0) {
674 exit = true;
675 break;
676 }
677 }
678
679 array[dest--] = tmp[cursor2--];
680
681 if (--length2 === 1) {
682 exit = true;
683 break;
684 }
685
686 count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);
687
688 if (count2 !== 0) {
689 dest -= count2;
690 cursor2 -= count2;
691 length2 -= count2;
692 customDest = dest + 1;
693 customCursor = cursor2 + 1;
694
695 for (i = 0; i < count2; i++) {
696 array[customDest + i] = tmp[customCursor + i];
697 }
698
699 if (length2 <= 1) {
700 exit = true;
701 break;
702 }
703 }
704
705 array[dest--] = array[cursor1--];
706
707 if (--length1 === 0) {
708 exit = true;
709 break;
710 }
711
712 minGallop--;
713 } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
714
715 if (exit) {
716 break;
717 }
718
719 if (minGallop < 0) {
720 minGallop = 0;
721 }
722
723 minGallop += 2;
724 }
725
726 this.minGallop = minGallop;
727
728 if (minGallop < 1) {
729 this.minGallop = 1;
730 }
731
732 if (length2 === 1) {
733 dest -= length1;
734 cursor1 -= length1;
735 customDest = dest + 1;
736 customCursor = cursor1 + 1;
737
738 for (i = length1 - 1; i >= 0; i--) {
739 array[customDest + i] = array[customCursor + i];
740 }
741
742 array[dest] = tmp[cursor2];
743 } else if (length2 === 0) {
744 throw new Error('mergeHigh preconditions were not respected');
745 } else {
746 customCursor = dest - (length2 - 1);
747 for (i = 0; i < length2; i++) {
748 array[customCursor + i] = tmp[i];
749 }
750 }
751 };
752
753 return TimSort;
754 })();
755
756 function sort(array, compare, lo, hi) {
757 if (!Array.isArray(array)) {
758 throw new TypeError('Can only sort arrays');
759 }
760
761 if (!compare) {
762 compare = alphabeticalCompare;
763 } else if (typeof compare !== 'function') {
764 hi = lo;
765 lo = compare;
766 compare = alphabeticalCompare;
767 }
768
769 if (!lo) {
770 lo = 0;
771 }
772 if (!hi) {
773 hi = array.length;
774 }
775
776 var remaining = hi - lo;
777
778 if (remaining < 2) {
779 return;
780 }
781
782 var runLength = 0;
783
784 if (remaining < DEFAULT_MIN_MERGE) {
785 runLength = makeAscendingRun(array, lo, hi, compare);
786 binaryInsertionSort(array, lo, hi, lo + runLength, compare);
787 return;
788 }
789
790 var ts = new TimSort(array, compare);
791
792 var minRun = minRunLength(remaining);
793
794 do {
795 runLength = makeAscendingRun(array, lo, hi, compare);
796 if (runLength < minRun) {
797 var force = remaining;
798 if (force > minRun) {
799 force = minRun;
800 }
801
802 binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
803 runLength = force;
804 }
805
806 ts.pushRun(lo, runLength);
807 ts.mergeRuns();
808
809 remaining -= runLength;
810 lo += runLength;
811 } while (remaining !== 0);
812
813 ts.forceMergeRuns();
814 }
815});
Note: See TracBrowser for help on using the repository browser.