|
1 |
| -import { loadUnsafe, storeUnsafe } from "./arraybuffer"; |
2 |
| -import { Array } from "../array"; |
| 1 | +import { |
| 2 | + loadUnsafeWithOffset, |
| 3 | + storeUnsafeWithOffset |
| 4 | +} from "./arraybuffer"; |
3 | 5 |
|
| 6 | +import { |
| 7 | + compareUnsafe, |
| 8 | +} from "./string"; |
| 9 | + |
| 10 | +/** Obtains the default comparator for the specified type. */ |
| 11 | +@inline |
4 | 12 | export function defaultComparator<T>(): (a: T, b: T) => i32 {
|
5 |
| - return function compare(a: T, b: T): i32 { |
6 |
| - return (<i32>(a > b) - <i32>(a < b)); |
7 |
| - }; |
| 13 | + if (isInteger<T>()) { |
| 14 | + if (isSigned<T>() && sizeof<T>() <= 4) { |
| 15 | + return (a: T, b: T): i32 => (<i32>(a - b)); |
| 16 | + } else { |
| 17 | + return (a: T, b: T): i32 => (<i32>(a > b) - <i32>(a < b)); |
| 18 | + } |
| 19 | + } else if (isFloat<T>()) { |
| 20 | + if (sizeof<T>() == 4) { |
| 21 | + return (a: T, b: T): i32 => { |
| 22 | + var ia = reinterpret<i32>(a); |
| 23 | + var ib = reinterpret<i32>(b); |
| 24 | + ia ^= (ia >> 31) >>> 1; |
| 25 | + ib ^= (ib >> 31) >>> 1; |
| 26 | + return <i32>(ia > ib) - <i32>(ia < ib); |
| 27 | + }; |
| 28 | + } else { |
| 29 | + return (a: T, b: T): i32 => { |
| 30 | + var ia = reinterpret<i64>(a); |
| 31 | + var ib = reinterpret<i64>(b); |
| 32 | + ia ^= (ia >> 63) >>> 1; |
| 33 | + ib ^= (ib >> 63) >>> 1; |
| 34 | + return <i32>(ia > ib) - <i32>(ia < ib); |
| 35 | + }; |
| 36 | + } |
| 37 | + } else if (isString<T>()) { |
| 38 | + return (a: T, b: T): i32 => { |
| 39 | + var sa = <string>a, sb = <string>b; |
| 40 | + return compareUnsafe(sa, 0, sb, 0, min(sa.length, sb.length)); |
| 41 | + }; |
| 42 | + } else { |
| 43 | + return (a: T, b: T): i32 => (<i32>(a > b) - <i32>(a < b)); |
| 44 | + } |
8 | 45 | }
|
9 | 46 |
|
10 |
| -export function insertionSort<T>(arr: Array<T>, comparator: (a: T, b: T) => i32): Array<T> { |
11 |
| - var buffer = arr.buffer_; |
12 |
| - for (let i: i32 = 0, length: i32 = arr.length; i < length; i++) { |
13 |
| - let a = loadUnsafe<T,T>(buffer, i); // a = arr[i] |
| 47 | +/** Sorts an Array with the 'Insertion Sort' algorithm. */ |
| 48 | +export function insertionSort<T>( |
| 49 | + buffer: ArrayBuffer, |
| 50 | + byteOffset: i32, |
| 51 | + length: i32, |
| 52 | + comparator: (a: T, b: T) => i32 |
| 53 | +): void { |
| 54 | + for (let i = 0; i < length; i++) { |
| 55 | + let a = loadUnsafeWithOffset<T,T>(buffer, i, byteOffset); // a = arr[i] |
14 | 56 | let j = i - 1;
|
15 | 57 | while (j >= 0) {
|
16 |
| - let b = loadUnsafe<T,T>(buffer, j); // b = arr[j] |
| 58 | + let b = loadUnsafeWithOffset<T,T>(buffer, j, byteOffset); // b = arr[j] |
17 | 59 | if (comparator(a, b) < 0) {
|
18 |
| - storeUnsafe<T,T>(buffer, j-- + 1, b); // arr[j + 1] = b |
| 60 | + storeUnsafeWithOffset<T,T>(buffer, j-- + 1, b, byteOffset); // arr[j + 1] = b |
19 | 61 | } else break;
|
20 | 62 | }
|
21 |
| - storeUnsafe<T,T>(buffer, j + 1, a); // arr[j + 1] = a |
| 63 | + storeUnsafeWithOffset<T,T>(buffer, j + 1, a, byteOffset); // arr[j + 1] = a |
22 | 64 | }
|
23 |
| - return arr; |
24 | 65 | }
|
25 | 66 |
|
26 |
| -export function weakHeapSort<T>(arr: Array<T>, comparator: (a: T, b: T) => i32): Array<T> { |
| 67 | +/** Sorts an Array with the 'Weak Heap Sort' algorithm. */ |
| 68 | +export function weakHeapSort<T>( |
| 69 | + buffer: ArrayBuffer, |
| 70 | + byteOffset: i32, |
| 71 | + length: i32, |
| 72 | + comparator: (a: T, b: T) => i32 |
| 73 | +): void { |
27 | 74 | const shift32 = alignof<u32>();
|
28 | 75 |
|
29 |
| - var length = arr.length; |
30 | 76 | var bitsetSize = (length + 31) >> 5 << shift32;
|
31 | 77 | var bitset = memory.allocate(bitsetSize); // indexed in 32-bit chunks below
|
32 | 78 | memory.fill(bitset, 0, bitsetSize);
|
33 | 79 |
|
34 | 80 | // see: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.21.1863&rep=rep1&type=pdf
|
35 | 81 |
|
36 |
| - var buffer = arr.buffer_; |
37 | 82 | for (let i = length - 1; i > 0; i--) {
|
38 | 83 | let j = i;
|
39 | 84 | while ((j & 1) == (load<u32>(bitset + (j >> 6 << shift32)) >> (j >> 1 & 31) & 1)) j >>= 1;
|
40 | 85 |
|
41 | 86 | let p = j >> 1;
|
42 |
| - let a = loadUnsafe<T,T>(buffer, p); // a = arr[p] |
43 |
| - let b = loadUnsafe<T,T>(buffer, i); // b = arr[i] |
| 87 | + let a = loadUnsafeWithOffset<T,T>(buffer, p, byteOffset); // a = arr[p] |
| 88 | + let b = loadUnsafeWithOffset<T,T>(buffer, i, byteOffset); // b = arr[i] |
44 | 89 | if (comparator(a, b) < 0) {
|
45 | 90 | store<u32>(
|
46 | 91 | bitset + (i >> 5 << shift32),
|
47 | 92 | load<u32>(bitset + (i >> 5 << shift32)) ^ (1 << (i & 31))
|
48 | 93 | );
|
49 |
| - storeUnsafe<T,T>(buffer, i, a); // arr[i] = a |
50 |
| - storeUnsafe<T,T>(buffer, p, b); // arr[p] = b |
| 94 | + storeUnsafeWithOffset<T,T>(buffer, i, a, byteOffset); // arr[i] = a |
| 95 | + storeUnsafeWithOffset<T,T>(buffer, p, b, byteOffset); // arr[p] = b |
51 | 96 | }
|
52 | 97 | }
|
53 | 98 |
|
54 | 99 | for (let i = length - 1; i >= 2; i--) {
|
55 |
| - let a = loadUnsafe<T,T>(buffer, 0); // a = arr[0] |
56 |
| - storeUnsafe<T,T>(buffer, 0, loadUnsafe<T,T>(buffer, i)); // arr[0] = arr[i] |
57 |
| - storeUnsafe<T,T>(buffer, i, a); // arr[i] = a |
| 100 | + let a = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset); |
| 101 | + storeUnsafeWithOffset<T,T>(buffer, 0, loadUnsafeWithOffset<T,T>(buffer, i, byteOffset), byteOffset); |
| 102 | + storeUnsafeWithOffset<T,T>(buffer, i, a, byteOffset); |
58 | 103 |
|
59 | 104 | let x = 1, y: i32;
|
60 | 105 | while ((y = (x << 1) + ((load<u32>(bitset + (x >> 5 << shift32)) >> (x & 31)) & 1)) < i) x = y;
|
61 | 106 |
|
62 | 107 | while (x > 0) {
|
63 |
| - a = loadUnsafe<T,T>(buffer, 0); // a = arr[0] |
64 |
| - let b = loadUnsafe<T,T>(buffer, x); // b = arr[x] |
| 108 | + a = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset); // a = arr[0] |
| 109 | + let b = loadUnsafeWithOffset<T,T>(buffer, x, byteOffset); // b = arr[x] |
65 | 110 |
|
66 | 111 | if (comparator(a, b) < 0) {
|
67 | 112 | store<u32>(
|
68 | 113 | bitset + (x >> 5 << shift32),
|
69 | 114 | load<u32>(bitset + (x >> 5 << shift32)) ^ (1 << (x & 31))
|
70 | 115 | );
|
71 |
| - storeUnsafe<T,T>(buffer, x, a); // arr[x] = a |
72 |
| - storeUnsafe<T,T>(buffer, 0, b); // arr[0] = b |
| 116 | + storeUnsafeWithOffset<T,T>(buffer, x, a, byteOffset); // arr[x] = a |
| 117 | + storeUnsafeWithOffset<T,T>(buffer, 0, b, byteOffset); // arr[0] = b |
73 | 118 | }
|
74 | 119 | x >>= 1;
|
75 | 120 | }
|
76 | 121 | }
|
77 | 122 |
|
78 | 123 | memory.free(bitset);
|
79 | 124 |
|
80 |
| - var t = loadUnsafe<T,T>(buffer, 1); // t = arr[1] |
81 |
| - storeUnsafe<T,T>(buffer, 1, loadUnsafe<T,T>(buffer, 0)); // arr[1] = arr[0] |
82 |
| - storeUnsafe<T,T>(buffer, 0, t); // arr[0] = t |
83 |
| - return arr; |
| 125 | + var t = loadUnsafeWithOffset<T,T>(buffer, 1, byteOffset); // t = arr[1] |
| 126 | + storeUnsafeWithOffset<T,T>(buffer, 1, loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset), byteOffset); |
| 127 | + storeUnsafeWithOffset<T,T>(buffer, 0, t, byteOffset); // arr[0] = t |
84 | 128 | }
|
0 commit comments